为什么exec不能在带有子功能的函数中工作?

时间:2022-06-09 02:29:15

It looks like you can't use exec in a function that has a subfunction...

看起来你不能在具有子功能的函数中使用exec ...

Anyone know why this Python code doesn't work? I get an error at the exec in test2. Also, I know exec's aren't good style, but trust me, I'm using exec for an appropriate reason. I wouldn't use it otherwise.

任何人都知道为什么这个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()

EDIT: I narrowed down the bug to having a function in a subfunction. It has nothing to do with the raise keyword.

编辑:我缩小了在子功能中具有功能的错误。它与raise关键字无关。

5 个解决方案

#1


61  

Correct. You can't use exec in a function that has a subfunction, unless you specify a context. From the docs:

正确。除非指定上下文,否则不能在具有子函数的函数中使用exec。来自文档:

If exec is used in a function and the function contains a nested block with free variables, the compiler will raise a SyntaxError unless the exec explicitly specifies the local namespace for the exec. (In other words, "exec obj" would be illegal, but "exec obj in ns" would be legal.)

如果在函数中使用了exec并且函数包含带有*变量的嵌套块,则编译器将引发SyntaxError,除非exec显式指定了exec的本地名称空间。 (换句话说,“exec obj”将是非法的,但“ns中的exec obj”将是合法的。)

There is good reason for this which I would probably understand if it wasn't Sunday night. Now, next question: Why are you using exec? It's very rarely needed. You say you have a good reason. I'm feeling sceptical about that. ;) If you have a good reason I'll tell you the workaround. :-P

这是有充分理由的,如果不是周日晚上,我可能会理解。现在,下一个问题:你为什么使用exec?这很少需要。你说你有充分的理由。我对此持怀疑态度。 ;)如果你有充分的理由我会告诉你解决方法。 :-P

Oh well, here it is anyway:

哦,好吧,无论如何:

def test2():
    """Test with a subfunction."""
    exec 'print "hi from test2"' in globals(), locals()
    def subfunction():
        return True

#2


24  

Although in Python it looks kind of like the local variables are stored in a dictionary locals(), they usually aren't. Instead they are mostly stored on the stack and accessed by index. This makes local variable lookup faster than if it had to do a dictionary lookup every time. If you use the locals() function then what you get is a fresh dictionary created from all the local variables, and that's why assigning to locals() doesn't generally work.

虽然在Python中看起来有点像局部变量存储在字典locals()中,但它们通常不是。相反,它们主要存储在堆栈中并通过索引访问。这使得局部变量查找比每次都必须进行字典查找更快。如果你使用locals()函数,那么你得到的是一个从所有局部变量创建的新字典,这就是为什么分配给locals()通常不起作用。

There are a couple of exceptions to this scenario:

这种情况有几个例外:

When you use an unqualified exec inside a function Python turns off the optimisation and uses a real dictionary for the local variables. That means you can create or update variables from inside the exec, but it also means all local variable access in that function will run more slowly.

当你在函数中使用非限定exec时,Python会关闭优化并使用真正的字典作为局部变量。这意味着您可以从exec内部创建或更新变量,但这也意味着该函数中的所有本地变量访问都将运行得更慢。

The other exception is that when you nest functions the inner function can access local variables in the outer function scope. When it does this the variable is stored in a 'cell' object instead of being stored on the stack. The extra level of indirection makes all use of scoped variables slower whether you access them from the inner or outer function.

另一个例外是当您嵌套函数时,内部函数可以访问外部函数作用域中的局部变量。当它执行此操作时,变量存储在“单元”对象中,而不是存储在堆栈中。除了从内部或外部函数访问它们之外,额外的间接级别使得所有范围变量的使用都变慢。

The catch that you've encountered is that these two exceptions to how local variables are normally stored are incompatible. You cannot have a variable stored in a dictionary and accessed through a cell reference at the same time. Python 2.x fixes this by disallowing the exec, even in cases like this where you aren't trying to use any scoped variables.

您遇到的问题是,通常存储局部变量的这两个例外是不兼容的。您不能将变量存储在字典中并同时通过单元格引用进行访问。 Python 2.x通过禁止exec来修复此问题,即使在这样的情况下,您也不会尝试使用任何作用域变量。

#3


4  

That works well in Python 3.1.3, after modifying the print statement to use print function.

在修改print语句以使用print函数之后,这在Python 3.1.3中运行良好。

In Python 2.6, it produces SyntaxError: unqualified exec is not allowed in function 'test2' it contains a nested function with free variables, I don't think it's a bug.

在Python 2.6中,它产生了SyntaxError:在函数'test2'中不允许使用非限定exec它包含一个带有*变量的嵌套函数,我不认为这是一个bug。

#4


3  

This is a rather interesting case:

这是一个相当有趣的案例:

>>> 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

The reason why this doesn't work indeed is that subfunction contains a free variable, and since in Python 2, exec could theoretically modify the locals in the containing scope, it would be impossible to decide if the variable should be bound from the global or the parent function scope. One of the verses in the Zen of Python is "In the face of ambiguity, refuse the temptation to guess." and this is what Python 2 does.

这不起作用的原因是子函数包含一个*变量,并且因为在Python 2中,exec理论上可以修改包含范围内的本地,所以不可能决定变量是否应该从全局变量或者父函数范围。 “禅宗之谜”中的一个经文是“面对模棱两可,拒绝猜测的诱惑。”这就是Python 2所做的。

Now the question is: what is this unbound variable? Well, it is the True!

现在的问题是:这个未绑定的变量是什么?嗯,这是真的!

Indeed it is reproduceable with None:

实际上它可以用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

Even though None cannot be assigned to, and it is considered as a constant in the bytecode, the buggy parser thinks it is an unbound variable here.

尽管无法分配None,并且它被视为字节码中的常量,但是错误的解析器认为它是一个未绑定的变量。

But if you replace it with 1 and it works without problems:

但是,如果你用1替换它,它没有问题:

>>> def test2():
...     exec('print "hi from func"')
...     def subfunction():
...         return 1
... 
>>>

To avoid this error, specify explicitly the globals and possibly locals that are to be used by exec, say:

要避免此错误,请明确指定exec要使用的全局变量和可能的本地变量,例如:

>>> def test2():
...     exec 'print "hi from test2"' in {}
...     def subfunction():
...         return None
...
>>>

In Python 3, exec is just a simple function and isn't handled specially by the parser or the bytecode compiler. In Python 3 exec cannot rebind function-local names, and thus this SyntaxError and ambiguity doesn't exist.

在Python 3中,exec只是一个简单的函数,并不是由解析器或字节码编译器专门处理的。在Python 3中,exec无法重新绑定函数本地名称,因此不存在此SyntaxError和歧义。


One peculiar case in Python 2 vs 3 compatibility is that while Python 2.7 documentation states that

Python 2与3兼容性的一个特殊情况是,虽然Python 2.7文档说明了这一点

The form exec(expr, globals) is equivalent to exec expr in globals, while the form exec(expr, globals, locals) is equivalent to exec expr in globals, locals. The tuple form of exec provides compatibility with Python 3, where exec is a function rather than a statement.

表单exec(expr,globals)等效于全局变量中的exec expr,而表单exec(expr,globals,locals)等同于globals,locals中的exec expr。 exec的元组形式提供与Python 3的兼容性,其中exec是函数而不是语句。

The tuple form has not always been 100 % compatible, as there was a bug in handling of exec in functions with nested functions (issue 21591); up to Python 2.7.8 the following code might have thrown an exception:

元组表单并不总是100%兼容,因为在嵌套函数的函数中处理exec时存在错误(issue 21591);直到Python 2.7.8,以下代码可能抛出异常:

def func():
    exec('print "hi from test2"', {})
    def subfunction():
        return None

This was fixed in Python 2.7.9 and it no longer throws.

这是在Python 2.7.9中修复的,它不再抛出。

#5


1  

The error seems to be fairly obvious to me:

这个错误对我来说似乎很明显:

SyntaxError: unqualified exec is not allowed in function 'test2' it contains a nested function with free variables

See pep 227 for more info: http://www.python.org/dev/peps/pep-0227/

有关详细信息,请参阅pep 227:http://www.python.org/dev/peps/pep-0227/

#1


61  

Correct. You can't use exec in a function that has a subfunction, unless you specify a context. From the docs:

正确。除非指定上下文,否则不能在具有子函数的函数中使用exec。来自文档:

If exec is used in a function and the function contains a nested block with free variables, the compiler will raise a SyntaxError unless the exec explicitly specifies the local namespace for the exec. (In other words, "exec obj" would be illegal, but "exec obj in ns" would be legal.)

如果在函数中使用了exec并且函数包含带有*变量的嵌套块,则编译器将引发SyntaxError,除非exec显式指定了exec的本地名称空间。 (换句话说,“exec obj”将是非法的,但“ns中的exec obj”将是合法的。)

There is good reason for this which I would probably understand if it wasn't Sunday night. Now, next question: Why are you using exec? It's very rarely needed. You say you have a good reason. I'm feeling sceptical about that. ;) If you have a good reason I'll tell you the workaround. :-P

这是有充分理由的,如果不是周日晚上,我可能会理解。现在,下一个问题:你为什么使用exec?这很少需要。你说你有充分的理由。我对此持怀疑态度。 ;)如果你有充分的理由我会告诉你解决方法。 :-P

Oh well, here it is anyway:

哦,好吧,无论如何:

def test2():
    """Test with a subfunction."""
    exec 'print "hi from test2"' in globals(), locals()
    def subfunction():
        return True

#2


24  

Although in Python it looks kind of like the local variables are stored in a dictionary locals(), they usually aren't. Instead they are mostly stored on the stack and accessed by index. This makes local variable lookup faster than if it had to do a dictionary lookup every time. If you use the locals() function then what you get is a fresh dictionary created from all the local variables, and that's why assigning to locals() doesn't generally work.

虽然在Python中看起来有点像局部变量存储在字典locals()中,但它们通常不是。相反,它们主要存储在堆栈中并通过索引访问。这使得局部变量查找比每次都必须进行字典查找更快。如果你使用locals()函数,那么你得到的是一个从所有局部变量创建的新字典,这就是为什么分配给locals()通常不起作用。

There are a couple of exceptions to this scenario:

这种情况有几个例外:

When you use an unqualified exec inside a function Python turns off the optimisation and uses a real dictionary for the local variables. That means you can create or update variables from inside the exec, but it also means all local variable access in that function will run more slowly.

当你在函数中使用非限定exec时,Python会关闭优化并使用真正的字典作为局部变量。这意味着您可以从exec内部创建或更新变量,但这也意味着该函数中的所有本地变量访问都将运行得更慢。

The other exception is that when you nest functions the inner function can access local variables in the outer function scope. When it does this the variable is stored in a 'cell' object instead of being stored on the stack. The extra level of indirection makes all use of scoped variables slower whether you access them from the inner or outer function.

另一个例外是当您嵌套函数时,内部函数可以访问外部函数作用域中的局部变量。当它执行此操作时,变量存储在“单元”对象中,而不是存储在堆栈中。除了从内部或外部函数访问它们之外,额外的间接级别使得所有范围变量的使用都变慢。

The catch that you've encountered is that these two exceptions to how local variables are normally stored are incompatible. You cannot have a variable stored in a dictionary and accessed through a cell reference at the same time. Python 2.x fixes this by disallowing the exec, even in cases like this where you aren't trying to use any scoped variables.

您遇到的问题是,通常存储局部变量的这两个例外是不兼容的。您不能将变量存储在字典中并同时通过单元格引用进行访问。 Python 2.x通过禁止exec来修复此问题,即使在这样的情况下,您也不会尝试使用任何作用域变量。

#3


4  

That works well in Python 3.1.3, after modifying the print statement to use print function.

在修改print语句以使用print函数之后,这在Python 3.1.3中运行良好。

In Python 2.6, it produces SyntaxError: unqualified exec is not allowed in function 'test2' it contains a nested function with free variables, I don't think it's a bug.

在Python 2.6中,它产生了SyntaxError:在函数'test2'中不允许使用非限定exec它包含一个带有*变量的嵌套函数,我不认为这是一个bug。

#4


3  

This is a rather interesting case:

这是一个相当有趣的案例:

>>> 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

The reason why this doesn't work indeed is that subfunction contains a free variable, and since in Python 2, exec could theoretically modify the locals in the containing scope, it would be impossible to decide if the variable should be bound from the global or the parent function scope. One of the verses in the Zen of Python is "In the face of ambiguity, refuse the temptation to guess." and this is what Python 2 does.

这不起作用的原因是子函数包含一个*变量,并且因为在Python 2中,exec理论上可以修改包含范围内的本地,所以不可能决定变量是否应该从全局变量或者父函数范围。 “禅宗之谜”中的一个经文是“面对模棱两可,拒绝猜测的诱惑。”这就是Python 2所做的。

Now the question is: what is this unbound variable? Well, it is the True!

现在的问题是:这个未绑定的变量是什么?嗯,这是真的!

Indeed it is reproduceable with None:

实际上它可以用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

Even though None cannot be assigned to, and it is considered as a constant in the bytecode, the buggy parser thinks it is an unbound variable here.

尽管无法分配None,并且它被视为字节码中的常量,但是错误的解析器认为它是一个未绑定的变量。

But if you replace it with 1 and it works without problems:

但是,如果你用1替换它,它没有问题:

>>> def test2():
...     exec('print "hi from func"')
...     def subfunction():
...         return 1
... 
>>>

To avoid this error, specify explicitly the globals and possibly locals that are to be used by exec, say:

要避免此错误,请明确指定exec要使用的全局变量和可能的本地变量,例如:

>>> def test2():
...     exec 'print "hi from test2"' in {}
...     def subfunction():
...         return None
...
>>>

In Python 3, exec is just a simple function and isn't handled specially by the parser or the bytecode compiler. In Python 3 exec cannot rebind function-local names, and thus this SyntaxError and ambiguity doesn't exist.

在Python 3中,exec只是一个简单的函数,并不是由解析器或字节码编译器专门处理的。在Python 3中,exec无法重新绑定函数本地名称,因此不存在此SyntaxError和歧义。


One peculiar case in Python 2 vs 3 compatibility is that while Python 2.7 documentation states that

Python 2与3兼容性的一个特殊情况是,虽然Python 2.7文档说明了这一点

The form exec(expr, globals) is equivalent to exec expr in globals, while the form exec(expr, globals, locals) is equivalent to exec expr in globals, locals. The tuple form of exec provides compatibility with Python 3, where exec is a function rather than a statement.

表单exec(expr,globals)等效于全局变量中的exec expr,而表单exec(expr,globals,locals)等同于globals,locals中的exec expr。 exec的元组形式提供与Python 3的兼容性,其中exec是函数而不是语句。

The tuple form has not always been 100 % compatible, as there was a bug in handling of exec in functions with nested functions (issue 21591); up to Python 2.7.8 the following code might have thrown an exception:

元组表单并不总是100%兼容,因为在嵌套函数的函数中处理exec时存在错误(issue 21591);直到Python 2.7.8,以下代码可能抛出异常:

def func():
    exec('print "hi from test2"', {})
    def subfunction():
        return None

This was fixed in Python 2.7.9 and it no longer throws.

这是在Python 2.7.9中修复的,它不再抛出。

#5


1  

The error seems to be fairly obvious to me:

这个错误对我来说似乎很明显:

SyntaxError: unqualified exec is not allowed in function 'test2' it contains a nested function with free variables

See pep 227 for more info: http://www.python.org/dev/peps/pep-0227/

有关详细信息,请参阅pep 227:http://www.python.org/dev/peps/pep-0227/