【问题标题】:calling execfile() in custom namespace executes code in '__builtin__' namespace在自定义命名空间中调用 execfile() 会在“__builtin__”命名空间中执行代码
【发布时间】:2010-10-17 04:47:24
【问题描述】:

当我在不传递 globals 或 locals 参数的情况下调用 execfile 时,它​​会在当前命名空间中创建对象,但如果我调用 execfile 并为 globals(和/或 locals)指定一个 dict,它会在 __builtin__ 命名空间中创建对象。

举个例子:

# exec.py
def myfunc():
    print 'myfunc created in %s namespace' % __name__

exec.py 是从 main.py 执行的文件,如下所示。

# main.py
print 'execfile in global namespace:'
execfile('exec.py')
myfunc()
print    

print 'execfile in custom namespace:'
d = {}
execfile('exec.py', d)
d['myfunc']()

当我从命令行运行 main.py 时,我得到以下输出。

execfile in global namespace:
myfunc created in __main__ namespace

execfile in custom namespace:
myfunc created in __builtin__ namespace

为什么在第二种情况下它在__builtin__命名空间中运行?

此外,如果我尝试从 __builtins__ 运行 myfunc,我会收到 AttributeError。 (这是我希望发生的事情,但是为什么__name__ 设置为__builtin__?)

>>> __builtins__.myfunc()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'module' object has no attribute 'myfunc'

谁能解释这种行为? 谢谢

【问题讨论】:

    标签: python namespaces


    【解决方案1】:

    首先,__name__ 不是命名空间 - 它是对其所属模块名称的引用,即:somemod.py -> somemod.__name__ == 'somemod' 例外情况是,如果您从命令行将模块作为可执行文件运行,则 __name__ 是 '__main__'。

    在您的示例中,幸运的是,您作为 main 运行的模块也被命名为 main。

    Execfile 执行模块的内容而不将其作为模块导入。因此,__name__ 没有被设置,因为它不是一个模块 - 它只是一个执行的代码序列。

    【讨论】:

    • 为什么它认为它的namebuiltin?这并没有真正回答我的问题。
    • David Locke 提供的答案涵盖了这一点——它在 python 文档中有所涵盖。
    • 不,不是,他的回答说 builtins 已添加到为本地人传入的字典中(除非我误解了)。
    【解决方案2】:

    execfile 函数类似于 exec 语句。如果您查看documentation for exec,您将看到以下解释该行为的段落。

    作为副作用,除了与执行代码设置的变量名相对应的那些之外,实现可能会在给定的字典中插入额外的键。例如,当前的实现可能会在键 __builtins__ (!) 下添加对内置模块 __builtin__ 的字典的引用。

    编辑:我现在看到我的答案适用于对问题标题的一种可能解释。我的回答不适用于实际提出的问题。

    【讨论】:

      【解决方案3】:

      顺便说一句,我更喜欢使用__import__() 而不是execfile

      module = __import__(module_name)
      value = module.__dict__[function_name](arguments)
      

      这在添加到 PYTHONPATH 时也很有效,因此可以导入其他目录中的模块:

      sys.path.insert(position, directory)
      

      【讨论】: