Это довольно интересный случай:
>>> 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 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
не может перепривязать имена локальных функций, и, таким образом, этой ошибки синтаксиса и неоднозначности не существует.
Один специфический случай совместимости с Python 2 и 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
в функциях с вложенными функциями (выпуск 21591) ; до Python 2.7.8 следующий код мог вызвать исключение:
def func():
exec('print "hi from test2"', {})
def subfunction():
return None
Это исправлено в Python 2.7.9 и больше не выдает.