Die kurze Antwort oder TL; DR
Grundsätzlich eval
wird verwendet , um eval Uate ein einziger dynamisch erzeugte Python Ausdruck und exec
wird verwendet exec ute dynamisch Python Code nur erzeugt , für die Nebenwirkungen.
eval
und exec
haben diese zwei Unterschiede:
eval
nur akzeptiert einzigen Ausdruck , exec
kann einen Codeblock nehmen , die Python - Anweisungen aufweist: Schleifen try: except:
, class
und die Funktion / Methode def
initions und so weiter.
Ein Ausdruck in Python ist alles, was Sie als Wert in einer Variablenzuweisung haben können:
a_variable = (anything you can put within these parentheses is an expression)
eval
Gibt den Wert des angegebenen Ausdrucks zurück, während exec
der Rückgabewert aus seinem Code ignoriert wird und immer zurückgegeben wird None
(in Python 2 ist es eine Anweisung und kann nicht als Ausdruck verwendet werden, sodass wirklich nichts zurückgegeben wird).
In den Versionen 1.0 - 2.7 exec
war dies eine Anweisung, da CPython eine andere Art von Codeobjekt für Funktionen erstellen musste, die exec
für ihre Nebenwirkungen innerhalb der Funktion verwendet wurden.
In Python 3 exec
ist eine Funktion; Ihre Verwendung hat keine Auswirkung auf den kompilierten Bytecode der Funktion, in der sie verwendet wird.
Also im Grunde:
>>> 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
Der compile
In- 'exec'
Modus kompiliert eine beliebige Anzahl von Anweisungen in einen Bytecode, der implizit immer zurückgibt None
, während er im 'eval'
Modus einen einzelnen Ausdruck in einen Bytecode kompiliert , der den Wert dieses Ausdrucks zurückgibt .
>>> 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
Im 'eval'
Modus (und damit mit der eval
Funktion, wenn eine Zeichenfolge übergeben wird) compile
löst das eine Ausnahme aus, wenn der Quellcode Anweisungen oder etwas anderes enthält, das über einen einzelnen Ausdruck hinausgeht:
>>> 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
Tatsächlich gilt die Anweisung "eval akzeptiert nur einen einzigen Ausdruck" nur, wenn eine Zeichenfolge (die Python- Quellcode enthält ) an übergeben wird eval
. Dann wird es intern mit Bytecode kompiliert. compile(source, '<string>', 'eval')
Hier kommt der Unterschied wirklich her.
Wenn ein code
Objekt (das Python- Bytecode enthält ) an exec
oder übergeben wird eval
, verhalten sie sich identisch , mit Ausnahme der Tatsache, dass exec
der Rückgabewert ignoriert wird und immer zurückgegeben wird None
. Es ist also möglich eval
, etwas auszuführen, das Anweisungen enthält, wenn Sie compile
es vorher nur in Bytecode geschrieben haben, anstatt es als Zeichenfolge zu übergeben:
>>> eval(compile('if 1: print("Hello")', '<string>', 'exec'))
Hello
>>>
funktioniert ohne Probleme, obwohl der kompilierte Code Anweisungen enthält. Es wird weiterhin zurückgegeben None
, da dies der Rückgabewert des Codeobjekts ist, von dem zurückgegeben wird compile
.
Im 'eval'
Modus (und damit mit der eval
Funktion, wenn eine Zeichenfolge übergeben wird) compile
löst das eine Ausnahme aus, wenn der Quellcode Anweisungen oder etwas anderes enthält, das über einen einzelnen Ausdruck hinausgeht:
>>> 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
Die längere Antwort, auch bekannt als die blutigen Details
exec
und eval
Die exec
Funktion (die in Python 2 eine Anweisung war ) wird zum Ausführen einer dynamisch erstellten Anweisung oder eines Programms verwendet:
>>> program = '''
for i in range(3):
print("Python is cool")
'''
>>> exec(program)
Python is cool
Python is cool
Python is cool
>>>
Die eval
Funktion macht das gleiche für einen einzelnen Ausdruck , und gibt den Wert des Ausdrucks:
>>> a = 2
>>> my_calculation = '42 * a'
>>> result = eval(my_calculation)
>>> result
84
exec
und eval
akzeptiert sowohl das Programm / Ausdruck als eine Person entweder werden str
, unicode
oder bytes
Objekt enthält Quellcode oder als code
Objekt , das Python Bytecode enthält.
Wenn ein str
// unicode
/ bytes
enthaltender Quellcode an übergeben wurde exec
, verhält er sich wie folgt:
exec(compile(source, '<string>', 'exec'))
und eval
verhält sich ähnlich wie:
eval(compile(source, '<string>', 'eval'))
Da alle Ausdrücke in Python als Anweisungen verwendet werden können (diese werden Expr
in der abstrakten Python- Grammatik als Knoten bezeichnet ; das Gegenteil ist nicht der Fall), können Sie sie immer verwenden, exec
wenn Sie den Rückgabewert nicht benötigen. Das heißt, Sie können entweder eval('my_func(42)')
oder verwenden exec('my_func(42)')
, mit dem Unterschied, dass eval
der von zurückgegebene Wert zurückgegeben my_func
und exec
verworfen wird:
>>> 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
>>>
Von den 2 nur exec
akzeptiert Quellcode, die Anweisungen enthält, wie def
, for
, while
, import
, oder class
, die Zuweisungsanweisung (aka a = 42
) oder ganze Programme:
>>> 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
Beide exec
und eval
akzeptieren 2 zusätzliche Positionsargumente - globals
und locals
-, die die globalen und lokalen Variablenbereiche sind, die der Code sieht. Diese sind standardmäßig auf globals()
und locals()
innerhalb des Bereichs, der aufgerufen hat, exec
oder eval
, aber jedes Wörterbuch kann für globals
und jedes mapping
für locals
(einschließlich dict
natürlich) verwendet werden. Diese können nicht nur verwendet werden, um die im Code exec
angezeigten Variablen einzuschränken / zu ändern, sondern werden häufig auch zum Erfassen der Variablen verwendet, die der uted-Code erstellt:
>>> g = dict()
>>> l = dict()
>>> exec('global a; a, b = 123, 42', g, l)
>>> g['a']
123
>>> l
{'b': 42}
(Wenn Sie den Wert des gesamten anzeigen g
, wäre es viel länger, weil exec
und eval
fügen Sie das eingebaute Modul __builtins__
automatisch zu den Globals hinzu, wenn es fehlt).
In Python 2 exec
lautet die offizielle Syntax für die Anweisung tatsächlich exec code in globals, locals
wie in
>>> exec 'global a; a, b = 123, 42' in g, l
Die alternative Syntax exec(code, globals, locals)
wurde jedoch immer auch akzeptiert (siehe unten).
compile
Die compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
integrierte Funktion kann verwendet werden, um wiederholte Aufrufe desselben Codes mit exec
oder eval
durch vorheriges Kompilieren der Quelle in ein code
Objekt zu beschleunigen . Der mode
Parameter steuert die Art des von der compile
Funktion akzeptierten Codefragments und die Art des von ihr erzeugten Bytecodes. Die Auswahlmöglichkeiten sind 'eval'
, 'exec'
und 'single'
:
'eval'
mode erwartet einen einzelnen Ausdruck und erzeugt einen Bytecode, der beim Ausführen den Wert dieses Ausdrucks zurückgibt :
>>> 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'
Akzeptiert alle Arten von Python-Konstrukten, von einzelnen Ausdrücken bis hin zu ganzen Codemodulen, und führt sie so aus, als wären sie Anweisungen der obersten Ebene des Moduls. Das Codeobjekt gibt Folgendes zurück 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'
eine beschränkte Form ist 'exec'
der einen , die einen Quellencode akzeptiert einzelne Anweisung (oder mehrere Anweisungen getrennt durch ;
) , wenn die letzte Anweisung ist eine Ausdrucksanweisung, die resultierende Bytecode auch druckt den repr
des Wertes dieses Ausdrucks in der Standardausgabe (!) .
Eine if
- elif
- else
Kette, eine Schleife mit else
und try
mit seinen except
, else
und finally
Blöcke wird eine einzelne Anweisung berücksichtigt.
Ein Quellfragment mit 2 Anweisungen der obersten Ebene ist ein Fehler für die 'single'
, außer in Python 2 gibt es einen Fehler , der manchmal mehrere Anweisungen der obersten Ebene im Code zulässt. nur der erste wird zusammengestellt; der Rest wird ignoriert:
In Python 2.7.8:
>>> exec(compile('a = 5\na = 6', '<string>', 'single'))
>>> a
5
Und in 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
Dies ist sehr nützlich, um interaktive Python-Shells zu erstellen. Der Wert des Ausdrucks wird jedoch nicht zurückgegeben , selbst wenn Sie eval
den resultierenden Code verwenden.
Die größte Unterscheidung von exec
und eval
kommt tatsächlich von der compile
Funktion und ihren Modi.
compile
Unterstützt neben dem Kompilieren von Quellcode zu Bytecode auch das Kompilieren abstrakter Syntaxbäume (Analysebäume von Python-Code) in code
Objekte. und Quellcode in abstrakte Syntaxbäume (der ast.parse
ist in Python geschrieben und ruft nur auf compile(source, filename, mode, PyCF_ONLY_AST)
); Diese werden beispielsweise zum schnellen Ändern des Quellcodes und auch zur dynamischen Codeerstellung verwendet, da es in komplexen Fällen häufig einfacher ist, den Code als Knotenbaum anstelle von Textzeilen zu behandeln.
Während Sie eval
nur eine Zeichenfolge auswerten können, die einen einzelnen Ausdruck enthält, können Sie eval
eine ganze Anweisung oder sogar ein ganzes Modul, das compile
in Bytecode umgewandelt wurde, verwenden. Das heißt, mit Python 2 print
ist eine Anweisung und kann nicht direkt eval
geführt werden:
>>> 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
es mit 'exec'
Modus in ein code
Objekt und Sie können eval
es ; Die eval
Funktion wird zurückgegeben 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
Wenn man sich in eval
und exec
Quellcode in CPython 3, dann ist dies sehr deutlich; Beide rufen PyEval_EvalCode
mit denselben Argumenten auf. Der einzige Unterschied besteht darin, dass sie exec
explizit zurückgegeben werdenNone
.
Syntaxunterschiede exec
zwischen Python 2 und Python 3
Einer der Hauptunterschiede in Python 2 besteht darin, dass exec
es sich um eine Anweisung und eval
eine integrierte Funktion handelt (beide sind in Python 3 integrierte Funktionen). Es ist eine bekannte Tatsache, dass die offizielle Syntax von exec
in Python 2 ist exec code [in globals[, locals]]
.
Im Gegensatz Mehrheit der Python 2-zu-3 - Portierung Führer scheinen vorzuschlagen , die exec
Aussage in CPython 2 kann auch mit Syntax verwendet wird, sieht genau wie der exec
Funktionsaufruf in Python 3. Der Grund dafür ist , dass Python 0.9.9 das hatte exec(code, globals, locals)
integrierte in Funktion! Und diese eingebaute Funktion wurde irgendwo vor der Veröffentlichung von Python 1.0 durch eine exec
Anweisung ersetzt .
Da es wünschenswert war, nicht zu brechen die Abwärtskompatibilität mit Python 0.9.9, eine Kompatibilität Hack 1993 Guido van Rossum hinzugefügt : Wenn das code
ein Tupel der Länge 2 oder 3 war, und globals
und locals
wurden nicht in die vergangen exec
sonst Aussage, die code
würde interpretiert werden als ob das zweite und dritte Element des Tupels waren globals
und locals
sind. Der Kompatibilitäts-Hack wurde selbst in der Python 1.4-Dokumentation (der frühesten online verfügbaren Version) nicht erwähnt . und war daher vielen Autoren der Portierungsanleitungen und -werkzeuge nicht bekannt, bis sie im November 2012 erneut dokumentiert wurden :
Der erste Ausdruck kann auch ein Tupel der Länge 2 oder 3 sein. In diesem Fall müssen die optionalen Teile weggelassen werden. Das Formular exec(expr, globals)
entspricht exec expr in globals
, während das Formular exec(expr, globals, locals)
entspricht exec expr in globals, locals
. Die Tupelform von exec
bietet Kompatibilität mit Python 3, wobei exec
es sich eher um eine Funktion als um eine Anweisung handelt.
Ja, in CPython 2.7 wird es leicht als Vorwärtskompatibilitätsoption bezeichnet (warum die Leute darüber verwirren, dass es überhaupt eine Abwärtskompatibilitätsoption gibt), als es tatsächlich zwei Jahrzehnte lang für die Abwärtskompatibilität da war .
Während while exec
eine Anweisung in Python 1 und Python 2 und eine integrierte Funktion in Python 3 und Python 0.9.9 ist,
>>> exec("print(a)", globals(), {'a': 42})
42
hat sich in möglicherweise jeder weit verbreiteten Python-Version jemals identisch verhalten; und funktioniert auch in Jython 2.5.2, PyPy 2.3.1 (Python 2.7.6) und IronPython 2.6.1 (ein großes Lob an sie, die das undokumentierte Verhalten von CPython genau verfolgen).
Was Sie in Pythons 1.0 - 2.7 mit seinem Kompatibilitäts-Hack nicht tun können, ist, den Rückgabewert von exec
in einer Variablen zu speichern :
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
(was in Python 3 auch nicht nützlich wäre, da exec
immer zurückgegeben wird None
) oder einen Verweis an Folgendes übergeben exec
:
>>> call_later(exec, 'print(42)', delay=1000)
File "<stdin>", line 1
call_later(exec, 'print(42)', delay=1000)
^
SyntaxError: invalid syntax
Welches Muster, das jemand tatsächlich verwendet haben könnte, obwohl unwahrscheinlich;
Oder verwenden Sie es in einem Listenverständnis:
>>> [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
Das ist Missbrauch des Listenverständnisses (verwenden Sie for
stattdessen eine Schleife!).
[i for i in globals().values() if hasattr(i, '__call__')][0]
eine Aussage oder ein Ausdruck? Wenn es ein Ausdruck war, warum kann ich ihn nicht@
als Dekorateur verwenden?