Python 将exit()作为全局函数调用会导致KeyError

Python 将exit()作为全局函数调用会导致KeyError,python,dictionary,Python,Dictionary,我正在为我正在编写的程序编写模块管理器,我想将模块名称存储在字典中,然后引用它们并从globals()调用它们 我希望我能打电话给你 globals()[module_names[module_number]]() 这将调用exit()并关闭脚本,而得到的结果是错误: 回溯(最后一次调用):文件“a2.py”,第103行,在start()文件“a2.py”的第44行,在start menu()文件“a2.py”的第36行,在菜单调用模块(选项)文件“a2.py”的第50行,在调用模块全局()转

我正在为我正在编写的程序编写模块管理器,我想将模块名称存储在字典中,然后引用它们并从
globals()
调用它们

我希望我能打电话给你

globals()[module_names[module_number]]()
这将调用
exit()
并关闭脚本,而得到的结果是错误:

回溯(最后一次调用):文件“a2.py”,第103行,在start()文件“a2.py”的第44行,在start menu()文件“a2.py”的第36行,在菜单调用模块(选项)文件“a2.py”的第50行,在调用模块全局()转换器[int(模块编号)]

键错误:“退出”


exit
不在
globals()
中,因为它不是全局的,而是内置的

在Python中,“全局”名称空间是每个模块的名称空间,而不是系统范围的名称空间。有一个特殊的“内置”模块,它包含真正的系统范围内的东西,如和一些特殊的东西,如
exit


您可以使用访问此模块

解释器访问这个模块的方式有点古怪。全局查找的工作原理大致如下:

def get_global(global_namespace, name):
    try:
        return global_namespace[name]
    except KeyError:
        pass
    try:
        builtins = global_namespace['__builtins__']
    except KeyError:
        raise NameError(name)
    if isinstance(builtins, types.ModuleType):
        builtins = builtins.__dict__
    try:
        return builtins[name]
    except KeyError:
        raise NameError(name)
在一些地方有一些特殊的代码,比如用于构建函数对象的内部代码,可以确保如果覆盖普通的
globals
dictionary,
\uuuuuuuuuuuuuuuu
会被复制过来(除非您明确告诉它不要这样做)。当导入系统从您的模块源代码(或编译的
.pyc
)构建模块对象时,它调用
exec
,因此每个模块的全局结果都是正确的
\uuuuuu内置项


内置模块
中的大多数东西都在那里,因为它们被编译到其中(正如您从名称中所期望的那样);对于CPython,您可以在中看到源代码

但是请注意,
exit
不存在。事实上,它是由模块注入到
内置的
模块中的,该模块作为正常启动序列的一部分导入(除非禁用它)。您可以在和中看到执行此操作的代码。常数表示它是这样注入的


因此,当您在代码中键入
exit
,或在交互提示下,它会出现在
globals()['''''''''.'退出'.
globals()

但是,如果您想手动访问它,最好执行
导入内置程序
,并将其作为
内置程序访问。退出

虽然确实如此,但您很少想访问内置的
。无论如何退出
;如果要以编程方式退出,请调用,这是一个普通函数
builtins.exit
是一个特殊的
Quitter
对象,专门为交互使用而设计。(它有一个
repr
,如果您忘记了括号,它会给出一条有用的消息,还有一些额外的代码,可以让它更好地处理IDLE。)

事实上,常量上的文档明确表示:

…对于交互式解释器外壳非常有用,不应在程序中使用


exit
不在
globals()
中,因为它不是全局的,而是内置的

在Python中,“全局”名称空间是每个模块的名称空间,而不是系统范围的名称空间。有一个特殊的“内置”模块,它包含真正的系统范围内的东西,如和一些特殊的东西,如
exit


您可以使用访问此模块

解释器访问这个模块的方式有点古怪。全局查找的工作原理大致如下:

def get_global(global_namespace, name):
    try:
        return global_namespace[name]
    except KeyError:
        pass
    try:
        builtins = global_namespace['__builtins__']
    except KeyError:
        raise NameError(name)
    if isinstance(builtins, types.ModuleType):
        builtins = builtins.__dict__
    try:
        return builtins[name]
    except KeyError:
        raise NameError(name)
在一些地方有一些特殊的代码,比如用于构建函数对象的内部代码,可以确保如果覆盖普通的
globals
dictionary,
\uuuuuuuuuuuuuuuu
会被复制过来(除非您明确告诉它不要这样做)。当导入系统从您的模块源代码(或编译的
.pyc
)构建模块对象时,它调用
exec
,因此每个模块的全局结果都是正确的
\uuuuuu内置项


内置模块
中的大多数东西都在那里,因为它们被编译到其中(正如您从名称中所期望的那样);对于CPython,您可以在中看到源代码

但是请注意,
exit
不存在。事实上,它是由模块注入到
内置的
模块中的,该模块作为正常启动序列的一部分导入(除非禁用它)。您可以在和中看到执行此操作的代码。常数表示它是这样注入的


因此,当您在代码中键入
exit
,或在交互提示下,它会出现在
globals()['''''''''.'退出'.
globals()

但是,如果您想手动访问它,最好执行
导入内置程序
,并将其作为
内置程序访问。退出

虽然确实如此,但您很少想访问内置的
。无论如何退出
;如果要以编程方式退出,请调用,这是一个普通函数
builtins.exit
是一个特殊的
Quitter
对象,专门为交互使用而设计。(它有一个
repr
,如果您忘记了括号,它会给出一条有用的消息,还有一些额外的代码,可以让它更好地处理IDLE。)

事实上,常量上的文档明确表示:

…对于交互式解释器外壳非常有用,不应在程序中使用


-1号出口实际上不在内置区域内。它是现场注射的。如果您运行
python-S
来禁用站点,您会发现出口不在那里。@wim它在
内置的
中。它被注入到那里,而不是作为
bltinmodule.c
的一部分,这一事实并没有改变这一事实。但如果你认为我的答案不够长,我可以添加更多的信息……“这是一个内置的”是误导或掩饰-这是一个由站点修补的实例。与内置IMO有点不同。@wim我不认为这有任何误导性。它是
bui中的可调用对象