我发现了python exec()
函数的一个奇怪行为。代码如下:
variables = {
('foo', 6),
('bar', 42)
}
def func():
for varData in variables:
varName, varValue = varData
localVarToEvaluate = varName + ' = varValue'
try:
#exec(localVarToEvaluate, globals(), locals())
exec(localVarToEvaluate)
except Exception as err:
print(str(err))
if varName not in locals():
print("Variable names '", varName, "can't be found in local scope!")
if 'foo' in locals():
print("'foo' OK:", foo) # exception here
else:
print("'foo' not available!")
if 'bar' in locals():
print("'bar' OK:", bar)
else:
print("'bar' not available!")
func()
我希望变量foo
和bar
在结束时由exec()
调用创建并打印,Python2.7就是这样。以上所有内容(在3.3、3.4、3.6和3.7上测试)都会引发异常,即foo
未定义:
奇怪的是,foo
和{locals()
、globals()
或{if
语句确认)看到的,但是代码/解释器却看不到它。
更奇怪的是,调试这个脚本并解析任何变量都是成功的(我在# exception here
上设置了一个断点,并使用VS代码在调试窗口中键入foo
。foo
已正确解析为值“6”。在
如果相同的代码(函数func()
中的内容)没有包装在函数中,那么这将按预期工作,foo
和{
你知道这里发生了什么吗?在
更新:我进一步简化了这个问题:
# take 1, create local variable 'foo' with value 6. Not in function.
varName = 'foo'
varValue = 42
localVarToEvaluate = varName + ' = varValue'
try:
exec(localVarToEvaluate)
except Exception as err:
print(str(err))
if 'foo' in locals():
# print(locals()['foo']) # (1)
# print(foo) # (2)
print("'foo' OK:", foo) # (3)
# take 2, create local variable 'bar' with value 42
def func2():
varName = 'bar'
varValue = 42
localVarToEvaluate = varName + ' = varValue'
try:
exec(localVarToEvaluate)
except Exception as err:
print(str(err))
if 'bar' in locals():
# print(locals()['bar']) # (1)
# print(bar) # (2)
#print("'bar' OK:", bar) # (3)
pass # uncomment any line above
func2()
执行此代码时,首先:
'foo' OK: 6
打印,然后引发此异常:
Exception has occurred: NameError
name 'bar' is not defined
...
注意,这两个代码是相同的,除了'bar'变量是在函数func2()
内创建的。在
我感兴趣的不是解决办法而是解释,为什么会这样,为什么第(1)点有效,而(2)和(3)点不起作用。注意,bar
变量可以在locals()
中看到,但不能通过直接调用它来访问它-但前提是它是在函数内部创建的!在
I've reported a bug on a Python Issue Tracker,官方的回答是:
总之,以这种方式使用的
exec()
在函数内部是没有用的。在很多关于这个问题的不清楚的问题用OP解决了。见答案编辑。它可以归结为(导入)钩住局部变量(变量、def、类),以便在定义中使用它们。在
请看下面的答案和内联评论什么是什么和为什么。在
如您所见,我(import)创建了一个指向本地变量的钩子,varName'bar'将在定义中使用
self
。它可以是任何名称t.b.h.请参见self
上的pydocs,等等结果是:
^{pr2}$如果
print('\n\n', locals())
在func()下面,您将得到以下打印结果:在第7项中,您可以看到func2链接。在
更新4:
在Python2.7.16和3.5.2之间切换显示locals()dict没有变化,globals()dict有一个变化,如下所示。在
在2.7中:
'variables': set([('bar', 42), ('foo', 6)])
在3.5中:
'variables': {('bar', 42), ('foo', 6)}
。。。这个
set()
在我看来,它不再像您在3.5中提到的那样有效。在我试过改编你的剧本:
然后。。。可能还是执行官。所以我禁用了运行}。在
func()
,并且globals()
中的差别仍然存在。所以我认为这是globals()
函数的区别,而不是{相关问题 更多 >
编程相关推荐