[英]Why doesn't exec work in a function with a subfunction?
看起来您不能在具有子功能的函数中使用exec ...
有人知道为什么这个Python代码不起作用吗? 我在test2中的exec处收到错误。 另外,我知道exec的风格不好,但是请相信我,出于适当的原因,我正在使用exec。 否则我不会使用它。
#!/usr/bin/env python
#
def test1():
exec('print "hi from test1"')
test1()
def test2():
"""Test with a subfunction."""
exec('print "hi from test2"')
def subfunction():
return True
test2()
编辑:我将错误缩小为在子功能中具有功能。 它与raise关键字无关。
正确。 除非指定上下文,否则不能在具有子功能的函数中使用exec。 从文档:
如果在函数中使用了exec并且该函数包含带有自由变量的嵌套块,则除非exec显式指定exec的本地名称空间,否则编译器将引发SyntaxError。 (换句话说,“ exec obj”将是非法的,但“ ns中的exec obj”将是合法的。)
有充分的理由,如果不是星期天晚上,我可能会明白。 现在,下一个问题:为什么要使用exec? 很少需要它。 你说你有充分的理由。 我对此表示怀疑。 ;)如果您有充分的理由,我会告诉您解决方法。 :-P
哦,好了,这仍然是:
def test2():
"""Test with a subfunction."""
exec 'print "hi from test2"' in globals(), locals()
def subfunction():
return True
尽管在Python中看起来局部变量似乎存储在字典locals()
,但通常不是。 相反,它们通常存储在堆栈中,并通过索引进行访问。 这使得局部变量查找的速度比每次必须进行字典查找的速度都要快。 如果使用locals()
函数,则得到的是从所有局部变量创建的新字典,这就是为什么分配给locals()
通常不起作用的原因。
此方案有两个例外:
当您在函数内部使用不合格的exec
Python会关闭优化功能,并为局部变量使用真正的字典。 这意味着您可以在exec
内部创建或更新变量,但这也意味着该函数中的所有局部变量访问将运行得更慢。
另一个例外是,当您嵌套函数时,内部函数可以访问外部函数范围内的局部变量。 执行此操作时,变量将存储在“单元”对象中,而不是存储在堆栈中。 无论是从内部函数还是外部函数访问范围变量,额外的间接级别都会使作用域变量的使用变慢。
您遇到的问题是,通常如何存储局部变量的这两个例外是不兼容的。 您不能将变量存储在字典中并同时通过单元格引用进行访问。 Python 2.x通过禁止exec来解决此问题,即使在这种情况下,您也不想使用任何作用域变量。
这是一个很有趣的情况:
>>> def func():
... exec('print "hi from func"')
... def subfunction():
... return True
...
File "<stdin>", line 2
SyntaxError: unqualified exec is not allowed in function 'func' because
it contains a nested function with free variables
确实不起作用的原因是subfunction
包含一个自由变量,并且由于在Python 2中, exec
在理论上可以修改包含作用域中的局部变量,因此无法确定该变量是否应与全局变量绑定,父函数范围。 Python Zen中的其中一句诗是“面对模棱两可,拒绝猜测的诱惑”。 这就是Python 2所做的。
现在的问题是:这个自由(未绑定)变量是什么? 好吧,这是True
!
实际上,可以使用None
复制它:
>>> def func():
... exec('print "hi from func"')
... def subfunction():
... return None
...
File "<stdin>", line 2
SyntaxError: unqualified exec is not allowed in function 'test2' because it contains a nested
function with free variables
即使无法将None
赋值,并且在字节码中将其视为常量 ,但越野车解析器仍认为此处是未绑定的变量。
但是,如果将其替换为1
并且可以正常使用,则可以:
>>> def test2():
... exec('print "hi from func"')
... def subfunction():
... return 1
...
>>>
为避免此错误,请显式指定exec
将使用的全局变量和可能的局部变量,例如:
>>> def test2():
... exec 'print "hi from test2"' in {}
... def subfunction():
... return None
...
>>>
在Python 3中, exec
只是一个简单的函数,不会由解析器或字节码编译器专门处理。 在Python 3中, exec
无法重新绑定函数本地名称,因此此SyntaxError和歧义不存在。
Python 2 vs 3兼容性的一种特殊情况是,尽管Python 2.7文档指出:
形式
exec(expr, globals)
等同于exec expr in globals
,而形式exec(expr, globals, locals)
等同于exec expr in globals, locals
。exec
的元组形式提供了与Python 3的兼容性,其中exec
是函数而不是语句。
元组形式并不总是100%兼容的,因为在处理带有嵌套函数的函数中exec
存在错误(issue 21591) ; 在Python 2.7.8之前,以下代码可能引发了异常:
def func():
exec('print "hi from test2"', {})
def subfunction():
return None
这已在Python 2.7.9中修复,并且不再抛出。
在修改print语句以使用print函数之后,在Python 3.1.3中效果很好。
在Python 2.6中,它会产生SyntaxError: unqualified exec is not allowed in function 'test2' it contains a nested function with free variables
,我认为这不是错误。
该错误对我来说似乎很明显:
SyntaxError: unqualified exec is not allowed in function 'test2' it contains a nested function with free variables
有关更多信息,请参见pep 227: http : //www.python.org/dev/peps/pep-0227/
dict
和list
理解也可能被视为Python 2.7.5的子函数
例如,这在Python 2.7.5上失败,但在Python 2.7.12上有效:
def func():
exec('print("a")')
(str(e) for e in range(10))
与:
File "./a.py", line 4
exec('print("a")')
SyntaxError: unqualified exec is not allowed in function 'func' it contains a nested function with free variables
它可能在内部被编译为字节码中的函数。
TODO查找修复提交。 这超出了我的git log --grep
foo。
类似dict
理解:
def func():
exec('print("a")', {e:str(e) for e in range(10)})
这是特别糟糕的,因为它是global
参数的通用参数。
还提出了: https : //github.com/sphinx-doc/sphinx/issues/5417#issuecomment-421731085
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.