python exec在2.7和3.3之间表现不同

时间:2016-01-05 23:08:27

标签: python python-2.7 python-3.x exec

以下代码片段从Python 2.7和3.3获得不同的输出。

data = {'_out':[1,2,3,3,4]}
codes = ['_tmp=[]',
         '[_tmp.append(x) for x in _out if x not in _tmp]',
         'print(_tmp)']
for c in codes:
    exec(c,{},data)

Python 2.7的输出:

[1,2,3,4]

Python 3.3的输出:

Traceback (most recent call last):
  File "test.py", line 8, in <module>
    exec(c,{},data)
  File "<string>", line 1, in <module>
  File "<string>", line 1, in <listcomp>
NameError: global name '_tmp' is not defined

要修复Python 3.3中的错误,我只需将全局变量设置为与本地变量相同,即exec(c,data,data)。知道为什么Python 3.3不像2.7那样表现吗?

1 个答案:

答案 0 :(得分:2)

似乎已知并且期望的行为,请参阅问题13557 https://bugs.python.org/issue13557

进一步

https://docs.python.org/3/reference/executionmodel.html#interaction-with-dynamic-features

  

eval()和exec()函数无权访问用于解析名称的完整环境。可以在调用者的本地和全局名称空间中解析名称。 自由变量不会在最近的封闭命名空间中解析,而是在全局命名空间中解析

您可以通过不使用列表理解和局部变量方法调用,或通过全局范围提供变量来解决上述问题

改为循环

data = {'_out':[1,2,3,3,4]}
codes = ['_tmp=[]', """
for x in _out: 
  if x not in _tmp: 
    _tmp.append(x)
""",
         'print(_tmp)']

for c in codes:
    exec(c, {}, data)

全球环境

data = {'_out':[1,2,3,3,4]}
codes = ['_tmp=[]',
         '[_tmp.append(x) for x in _out if x not in _tmp]',
         'print(_tmp)']
for c in codes:
    exec(c, data)