我正在为当前正在编写的程序编写模块管理器,我想将模块名称存储在字典中,然后引用它们并从globals()
进行调用。
module_number = 5
module_names = ["", "quiz", "scores", "gender", "help", "exit"]
然后我希望我可以打电话
globals()[module_names[module_number]]()
哪个会调用exit()
并关闭脚本,而是出现错误:
回溯(最近一次通话最近):start()中的文件“ a2.py”,第103行,开始菜单中的文件“ a2.py”,第44行,开始menu()文件“ a2.py”,第36行,在菜单中的call_module(choice)文件“ a2.py”,第50行,在call_module globals()converter [int(module_number)]
中KeyError:'退出'
答案 0 :(得分:6)
exit
不在globals()
中,因为它不是全局变量,而是内置变量。
在Python中,“全局”命名空间是按模块而不是系统范围的。有一个特殊的“内置”模块可以容纳真正在系统范围内的内容,例如the normal builtin functions和一些特殊的东西,例如exit
。
您可以使用import builtins
访问此模块。
解释器访问此模块的方式有点时髦。全局查找大致如下:
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)
在exec
之类的地方有特殊的代码,以及用于构建函数对象的内部代码,可确保如果您覆盖普通的globals
字典,__builtins__
将被复制(除非您明确地告诉它不要)。导入系统从模块源(或编译的.pyc
)构建模块对象时,它将调用exec
,因此每个模块的全局变量都以正确的__builtins__
结尾。
builtins
模块中的大多数内容都在那儿,因为它们已被编译到其中(正如您期望的那样);对于CPython,您可以在Python/bltinmodule.c
中查看源代码。
但是请注意,exit
不存在。实际上,它是由site
模块注入到builtins
模块中的,该模块是正常启动序列的一部分(除非您禁用它)被导入。您可以在Lib/site.py
和Lib/_sitebuiltins.py
中查看执行此操作的代码。 exit
常量表示它是通过这种方式注入的。
因此,当您在代码中或在交互式提示符下键入exit
时,可以在globals()['__builtins__']['exit']
或globals()['__builtins__'].__dict__['exit']
中找到它。
但是,如果要手动访问它,则最好进行import builtins
并以builtins.exit
的身份访问。
尽管确实如此,但是您仍然很少希望访问builtins.exit
;如果要以编程方式退出,请调用sys.exit
,这是正常功能。 builtins.exit
是特殊的Quitter
对象,专门用于交互式使用。 (它有一个repr
,如果您忘记了括号,它会提供有用的信息,并提供一些额外的代码使它在IDLE中可以正常使用。)
实际上,exit
常量上的文档明确表示它是:
...对交互式解释程序外壳很有用,不应在程序中使用。