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中的可调用对象