我正在为我正在编写的程序编写模块管理器,我想将模块名称存储在字典中,然后引用它们并从中调用它们globals()
.
module_number = 5
module_names = ["", "quiz", "scores", "gender", "help", "exit"]
Run Code Online (Sandbox Code Playgroud)
我希望我可以打电话
globals()[module_names[module_number]]()
Run Code Online (Sandbox Code Playgroud)
哪个会调用exit()
并关闭脚本,而是得到结果错误:
回溯(最近一次调用最后一次):文件"a2.py",第103行,在start()文件"a2.py",第44行,在开始菜单中()文件"a2.py",第36行,在菜单call_module中(选择)文件"a2.py",第50行,在call_module globals()转换器[int(module_number)]中
KeyError:'退出'
exit
不是globals()
因为它不是全球性的,所以它是内置的.
在Python中,"全局"命名空间是按模块进行的,而不是系统范围的.有一个特殊的"内置"模块,可以保存真正的系统范围内的东西,比如普通的内置函数和一些特殊的东西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)
Run Code Online (Sandbox Code Playgroud)
在像这样的地方有特殊的代码exec
,以及用于构建函数对象的内部代码,这确保了如果覆盖普通globals
字典,则会__builtins__
被复制(除非您明确告诉它不要).当导入系统从模块源(或编译.pyc
)中构建模块对象时,它会调用exec
,因此每个模块的全局变量都以右边结束__builtins__
.
builtins
模块中的大多数东西都在那里,因为它们被编译成它(正如你对名称所期望的那样); 对于CPython,你可以看到源代码Python/bltinmodule.c
.
但请注意exit
不存在.实际上,它是builtins
由site
模块注入到模块中的,该模块是作为正常启动序列的一部分导入的(除非您禁用它).您可以在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
常量上的文档明确地说它是:
...对交互式解释器shell很有用,不应该在程序中使用.