Я изучаю динамическую оценку кода Python и нахожусь в функциях eval() и compile() и в выражении exec.
Может кто-нибудь объяснить разницу между eval и exec и как вписываются различные режимы compile()?
Я изучаю динамическую оценку кода Python и нахожусь в функциях eval() и compile() и в выражении exec.
Может кто-нибудь объяснить разницу между eval и exec и как вписываются различные режимы compile()?
В принципе, eval используется для  eval для одного динамически генерируемого выражения Python и exec используется для  exec динамически генерируемого кода Python только для его побочных эффектов.
 eval и exec имеют следующие два отличия:
 eval принимает только  одиночное выражение, exec может принимать блок кода с инструкциями Python: циклы, try: except:, class и function/method def переходы и т.д.
Выражение в Python - это то, что вы можете иметь в качестве значения в присваивании переменной:
a_variable = (anything you can put within these parentheses is an expression)
 eval  возвращает значение данного выражения, тогда как exec игнорирует возвращаемое значение из своего кода и всегда возвращает None (в Python 2 это утверждение и не может использоваться как выражение, поэтому он действительно ничего не возвращает).
В версиях 1.0 - 2.7, exec был выражением, потому что CPython должен был создать другой тип кода для функций, которые использовали exec для его побочных эффектов внутри функции.
В Python 3 функция exec является функцией; он всегда создает один и тот же тип кодового объекта независимо от того, вызывается ли он внутри функций или в области модуля.
Таким образом, в основном:
>>> a = 5
>>> eval('37 + a')   # it is an expression
42
>>> exec('37 + a')   # it is an expression statement; value is ignored (None is returned)
>>> exec('a = 47')   # modify a global variable as a side effect
>>> a
47
>>> eval('a = 47')  # you cannot evaluate a statement
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    a = 47
      ^
SyntaxError: invalid syntax
Режим compile в 'exec' компилирует любое количество операторов в байт-код, который неявно всегда возвращает None, тогда как в режиме 'eval' он компилирует одно выражение в байт-код, который возвращает значение этого выражения.
>>> eval(compile('42', '<string>', 'exec'))  # code returns None
>>> eval(compile('42', '<string>', 'eval'))  # code returns 42
42
>>> exec(compile('42', '<string>', 'eval'))  # code returns 42,
>>>                                          # but ignored by exec
В режиме 'eval' (и, следовательно, с функцией eval, если строка передана), compile вызывает исключение, если исходный код содержит утверждения или что-либо еще за пределами одного выражения:
>>> compile('for i in range(3): print(i)', '<string>', 'eval')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    for i in range(3): print(i)
      ^
SyntaxError: invalid syntax
Фактически утверждение "eval принимает только одно выражение" применяется только тогда, когда строка (содержащая исходный код Python) передается на eval. Затем он внутренне скомпилирован в байт-код, используя compile(source, '<string>', 'eval'). Именно здесь происходит различие.
Если объект code (который содержит байт-код Python) передается в exec или eval, они ведут себя одинаково, за исключением того, что exec игнорирует возвращаемое значение, все еще возвращая None. Таким образом, можно использовать eval для выполнения чего-то, что имеет инструкции, если вы просто compile d его в байт-код перед тем, чтобы передать его как строку:
>>> eval(compile('if 1: print("Hello")', '<string>', 'exec'))
Hello
>>>
работает без проблем, хотя скомпилированный код содержит инструкции. Он по-прежнему возвращает None, потому что это возвращаемое значение объекта кода, возвращаемого из compile.
В режиме 'eval' (и, следовательно, с функцией eval, если строка передана), compile вызывает исключение, если исходный код содержит утверждения или что-либо еще за пределами одного выражения:
>>> compile('for i in range(3): print(i)', '<string>'. 'eval')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    for i in range(3): print(i)
      ^
SyntaxError: invalid syntax
exec и evalФункция exec (которая была инструкция в Python 2) используется для выполнения динамически созданного оператора или программы:
>>> program = '''
for i in range(3):
    print("Python is cool")
'''
>>> exec(program)
Python is cool
Python is cool
Python is cool
>>> 
Функция eval делает то же самое для одно выражение и возвращает значение выражения:
>>> a = 2
>>> my_calculation = '42 * a'
>>> result = eval(my_calculation)
>>> result
84
 exec и eval оба принимают программу/выражение для запуска либо как объект str, unicode или bytes, содержащий исходный код, либо как объект code, который содержит байт-код Python.
Если a str/unicode/bytes, содержащий исходный код, был передан в exec, он ведет себя эквивалентно:
exec(compile(source, '<string>', 'exec'))
и eval аналогично ведет себя эквивалентно:
eval(compile(source, '<string>', 'eval'))
Так как все выражения могут использоваться в качестве операторов в Python (они называются узлами Expr в абстрактной грамматике Python ; не верно), вы всегда можете использовать exec, если вам не требуется возвращаемое значение. То есть вы можете использовать eval('my_func(42)') или exec('my_func(42)'), разница в том, что eval возвращает значение, возвращаемое my_func, и exec отбрасывает его:
>>> def my_func(arg):
...     print("Called with %d" % arg)
...     return arg * 2
... 
>>> exec('my_func(42)')
Called with 42
>>> eval('my_func(42)')
Called with 42
84
>>> 
Из 2 только exec принимает исходный код, содержащий инструкции, такие как def, for, while, import или class, оператор присваивания (aka a = 42), или целые программы:
>>> exec('for i in range(3): print(i)')
0
1
2
>>> eval('for i in range(3): print(i)')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    for i in range(3): print(i)
      ^
SyntaxError: invalid syntax
Оба exec и eval принимают 2 дополнительных позиционных аргумента - globals и locals - которые являются глобальными и локальными областями переменных, которые видит код. Они по умолчанию соответствуют globals() и locals() в пределах области действия, которая называется exec или eval, но любой словарь может использоваться для globals и любого mapping для locals (включая dict, конечно). Они могут использоваться не только для ограничения/изменения переменных, которые видит код, но также часто используются для захвата переменных, создаваемых exec -требованным кодом:
>>> g = dict()
>>> l = dict()
>>> exec('global a; a, b = 123, 42', g, l)
>>> g['a']
123
>>> l
{'b': 42}
(Если вы отобразите значение всего g, это будет намного больше, потому что exec и eval автоматически добавить встроенный модуль как __builtins__ в глобальные переменные, если он отсутствует).
В Python 2 официальный синтаксис для оператора exec на самом деле exec code in globals, locals, как в
>>> exec 'global a; a, b = 123, 42' in g, l
Однако альтернативный синтаксис exec(code, globals, locals) всегда был принят (см. ниже).
compileВстроенный compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1) может использоваться для ускорения повторных вызовов одного и того же кода с помощью exec или eval на предварительно скомпилировав источник в объект code. Параметр mode контролирует тип фрагмента кода, который принимает функция compile, и тип создаваемого байт-кода. Возможные варианты: 'eval', 'exec' и 'single':
 'eval' режим ожидает одно выражение и будет генерировать байт-код, который, когда run вернет значение  этого выражения:
>>> dis.dis(compile('a + b', '<string>', 'eval'))
  1           0 LOAD_NAME                0 (a)
              3 LOAD_NAME                1 (b)
              6 BINARY_ADD
              7 RETURN_VALUE
 'exec' принимает любые типы конструкций python из отдельных выражений во все модули кода и выполняет их, как если бы они были модулями операторов верхнего уровня. Объект кода возвращает None:
>>> dis.dis(compile('a + b', '<string>', 'exec'))
  1           0 LOAD_NAME                0 (a)
              3 LOAD_NAME                1 (b)
              6 BINARY_ADD
              7 POP_TOP                             <- discard result
              8 LOAD_CONST               0 (None)   <- load None on stack
             11 RETURN_VALUE                        <- return top of stack
 'single' является ограниченной формой 'exec', которая принимает исходный код, содержащий оператор  single (или несколько операторов, разделенных символом ;), если последний оператор является выражением, полученный байт-код также выводит repr значения этого выражения на стандартный вывод (!).
An if - elif - else, цикл с else и try с его блоками except, else и finally считается одним утверждением.
Исходный фрагмент, содержащий 2 оператора верхнего уровня, является ошибкой для 'single', за исключением Python 2, есть ошибка, которая иногда допускает несколько инструкций для дополнения в коде; только первый компилируется; остальные игнорируются:
В Python 2.7.8:
>>> exec(compile('a = 5\na = 6', '<string>', 'single'))
>>> a
5
И в Python 3.4.2:
>>> exec(compile('a = 5\na = 6', '<string>', 'single'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    a = 5
        ^
SyntaxError: multiple statements found while compiling a single statement
Это очень полезно для создания интерактивных оболочек Python. Однако значение выражения не возвращается, даже если вы eval результирующий код.
Таким образом, наибольшее отличие exec и eval происходит от функции compile и ее режимов.
В дополнение к компиляции исходного кода в байт-код, compile поддерживает компиляцию абстрактных деревьев синтаксиса (разбора деревьев кода Python) в code объекты; и исходный код в абстрактные деревья синтаксиса (ast.parse написан на Python и просто вызывает compile(source, filename, mode, PyCF_ONLY_AST)); они используются, например, для изменения исходного кода на лету, а также для создания динамического кода, поскольку часто проще обрабатывать код как дерево узлов вместо строк текста в сложных случаях.
Пока eval позволяет вам оценивать строку, содержащую одно выражение, вы можете eval целой инструкции или даже целого модуля, который был compile d в байт-код; то есть с Python 2, print является инструкцией и не может быть eval приведен непосредственно:
>>> eval('for i in range(3): print("Python is cool")')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    for i in range(3): print("Python is cool")
      ^
SyntaxError: invalid syntax
 compile он с 'exec' режимом в объект code, и вы можете  eval it; функция eval вернет None.
>>> code = compile('for i in range(3): print("Python is cool")',
                   'foo.py', 'exec')
>>> eval(code)
Python is cool
Python is cool
Python is cool
Если вы посмотрите на eval и exec исходный код в CPython 3, это очень очевидно; они оба называют PyEval_EvalCode теми же аргументами, с той лишь разницей, что  exec явно возвращает None.
exec между Python 2 и Python 3Одно из основных различий в Python  2 заключается в том, что exec - это оператор, а eval - встроенная функция (оба являются встроенными функциями в Python 3).
Хорошо известно, что официальный синтаксис exec в Python 2 равен exec code [in globals[, locals]].
В отличие от большинства Python 2-to-3 porting руководства показаться чтобы предложить, оператор exec в CPython 2 также может использоваться с синтаксисом, который выглядит  точно, как exec вызов функции в Python 3. Причина в том, что Python 0.9.9 имел встроенную функцию exec(code, globals, locals)! И эта встроенная функция была заменена оператором exec где-то перед выпуском Python 1.0.
Поскольку было желательно не нарушать совместимость с Python 0.9.9, Гвидо ван Россум добавил взлом совместимости в 1993 году: если code был кортежем длины 2 или 3, а globals и locals не были переданы в оператор exec, иначе code будет интерпретироваться так, как если бы 2-й и 3-й элементы кортежа были globals и locals соответственно. Совместимость не упоминалась даже в документации Python 1.4 (самая ранняя доступная версия в Интернете); и, таким образом, не было известно многим писателям проводников и инструментов портирования до тех пор, пока не было документально снова в ноябре 2012 года:
Первое выражение может также быть кортежем длины 2 или 3. В этом случае необязательные части должны быть опущены. Форма
exec(expr, globals)эквивалентнаexec expr in globals, а формаexec(expr, globals, locals)эквивалентнаexec expr in globals, locals. Форма кортежаexecобеспечивает совместимость с Python 3, гдеexec- это функция, а не инструкция.
Да, в CPython 2.7 его можно назвать опцией прямой совместимости (зачем путать людей с тем, что есть опция обратной совместимости вообще), когда он фактически был там для обратной совместимости в течение двух десятилетий.
Таким образом, хотя exec является оператором в Python 1 и Python 2 и встроенной функцией в Python 3 и Python 0.9.9,
>>> exec("print(a)", globals(), {'a': 42})
42
имеет одинаковое поведение, возможно, в любой широко распространенной версии Python; и работает в Jython 2.5.2, PyPy 2.3.1 (Python 2.7.6) и IronPython 2.6.1 тоже (к ним относится неудовлетворительное поведение CPython).
То, что вы не можете сделать в Pythons 1.0 - 2.7 с его совместимостью, заключается в том, чтобы сохранить возвращаемое значение exec в переменную:
Python 2.7.11+ (default, Apr 17 2016, 14:00:29) 
[GCC 5.3.1 20160413] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a = exec('print(42)')
  File "<stdin>", line 1
    a = exec('print(42)')
           ^
SyntaxError: invalid syntax
(что также не полезно в Python 3, поскольку exec всегда возвращает None) или передает ссылку на exec:
>>> call_later(exec, 'print(42)', delay=1000)
  File "<stdin>", line 1
    call_later(exec, 'print(42)', delay=1000)
                  ^
SyntaxError: invalid syntax
Какой шаблон, который кто-то мог бы использовать, хотя и маловероятен;
Или используйте его в понимании списка:
>>> [exec(i) for i in ['print(42)', 'print(foo)']
  File "<stdin>", line 1
    [exec(i) for i in ['print(42)', 'print(foo)']
        ^
SyntaxError: invalid syntax
 который является злоупотреблением списками (используйте вместо этого цикл for!).
 exec не является выражением: инструкция в Python 2.x и функция в Python 3.x. Он компилирует и сразу оценивает оператор или набор операторов, содержащихся в строке. Пример:
exec('print(5)')           # prints 5.
# exec 'print 5'     if you use Python 2.x, nor the exec neither the print is a function there
exec('print(5)\nprint(6)')  # prints 5{newline}6.
exec('if True: print(6)')  # prints 6.
exec('5')                 # does nothing and returns nothing.
 eval - встроенная функция ( не инструкция), которая вычисляет выражение и возвращает значение, выражаемое выражением. Пример:
x = eval('5')              # x <- 5
x = eval('%d + 6' % x)     # x <- 11
x = eval('abs(%d)' % -100) # x <- 100
x = eval('x = 5')          # INVALID; assignment is not an expression.
x = eval('if 1: x = 4')    # INVALID; if is a statement, not an expression.
 compile - это версия более низкого уровня exec и eval. Он не выполняет или не оценивает ваши утверждения или выражения, а возвращает объект кода, который может это сделать. Режимы следующие:
compile(string, '', 'eval') возвращает объект кода, который был бы выполнен, если бы вы сделали eval(string). Обратите внимание, что вы не можете использовать операторы в этом режиме; действует только одно (одно) выражение.compile(string, '', 'exec') возвращает объект кода, который был бы выполнен, если бы вы сделали exec(string). Здесь вы можете использовать любое количество операторов.compile(string, '', 'single') похож на режим exec, но будет игнорировать все, кроме первого оператора. Обратите внимание, что оператор if/else с его результатами рассматривается как один оператор.exec для оператора и ничего не возвращает. eval предназначен для выражения и возвращает значение выражения.
выражение означает "что-то", в то время как утверждение означает "сделать что-то".