繁体   English   中英

exec为什么不能在具有子功能的功能中工作?

[英]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/

dictlist理解也可能被视为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM