Python 将类似字典的对象传递给exec而不是dict对象会更改附件的范围

Python 将类似字典的对象传递给exec而不是dict对象会更改附件的范围,python,Python,这是怎么回事 global_function = """ x = "Hello World" def print_global_x(): print(x) print_global_x() """ exec(global_function, {"__builtins__": builtins}) 但这个看似等效的例子不起作用 import builtins class TestEnvironment(dict): pass global_env = TestEnvironm

这是怎么回事

global_function = """
x = "Hello World"
def print_global_x():
    print(x)
print_global_x()
"""

exec(global_function, {"__builtins__": builtins})
但这个看似等效的例子不起作用

import builtins
class TestEnvironment(dict):
    pass

global_env = TestEnvironment()
global_env['__builtins__'] = builtins
exec(global_function, global_env)
第二个示例给出了一个错误,即x没有定义,但第一个示例运行良好。实际上,第二个示例对代码的求值似乎就像它被封装在一个类定义中一样,这是两个dict对象被传递给exec函数的情况,如文档中所述

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-6-edb1f5a14344> in <module>()
      9 """
     10 
---> 11 exec(global_function, global_env)

<string> in <module>()

<string> in print_global_x()

NameError: name 'x' is not defined
---------------------------------------------------------------------------
NameError回溯(最近一次呼叫上次)
在()
9 """
10
--->11执行官(全局函数、全局环境)
在()
打印中\u全局\u x()
名称错误:未定义名称“x”

我找到了原因。显然,python 3.5.0中有一个bug已被python 3.5.1解决。我只是更新了我的python版本,代码就可以运行了。谢谢大家。

我的猜测:您实现了一个类似字典的对象,您说它是您的环境。这个对象允许类似于听写的设置,但在您运行co时不会访问它de,全局空间正试图将数据存储到您的对象中,它成功地存储了数据,但却找不到x,因为没有etattr,也找不到x。我不认为是这样,因为如果我不定义方法getitem,它是从父类继承的。事实上,我可以复制错误,即使我同时删除了这两个get事实上,我应该这样做,以创建最小失败测试。