Die kurze Antwort oder TL; DR
Grundsätzlich evalwird verwendet , um eval Uate ein einziger dynamisch erzeugte Python Ausdruck und execwird verwendet exec ute dynamisch Python Code nur erzeugt , für die Nebenwirkungen.
evalund exechaben diese zwei Unterschiede:
evalnur akzeptiert einzigen Ausdruck , execkann einen Codeblock nehmen , die Python - Anweisungen aufweist: Schleifen try: except:, classund die Funktion / Methode definitions 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 execder 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 execwar dies eine Anweisung, da CPython eine andere Art von Codeobjekt für Funktionen erstellen musste, die execfür ihre Nebenwirkungen innerhalb der Funktion verwendet wurden.
In Python 3 execist 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 compileIn- '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 evalFunktion, wenn eine Zeichenfolge übergeben wird) compilelö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 codeObjekt (das Python- Bytecode enthält ) an execoder übergeben wird eval, verhalten sie sich identisch , mit Ausnahme der Tatsache, dass execder 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 compilees 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 evalFunktion, wenn eine Zeichenfolge übergeben wird) compilelö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 execFunktion (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 evalFunktion 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
execund evalakzeptiert sowohl das Programm / Ausdruck als eine Person entweder werden str, unicodeoder bytesObjekt enthält Quellcode oder als codeObjekt , das Python Bytecode enthält.
Wenn ein str// unicode/ bytesenthaltender Quellcode an übergeben wurde exec, verhält er sich wie folgt:
exec(compile(source, '<string>', 'exec'))
und evalverhält sich ähnlich wie:
eval(compile(source, '<string>', 'eval'))
Da alle Ausdrücke in Python als Anweisungen verwendet werden können (diese werden Exprin der abstrakten Python- Grammatik als Knoten bezeichnet ; das Gegenteil ist nicht der Fall), können Sie sie immer verwenden, execwenn 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 evalder von zurückgegebene Wert zurückgegeben my_funcund execverworfen 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 execakzeptiert 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 execund evalakzeptieren 2 zusätzliche Positionsargumente - globalsund 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, execoder eval, aber jedes Wörterbuch kann für globalsund jedes mappingfür locals(einschließlich dictnatürlich) verwendet werden. Diese können nicht nur verwendet werden, um die im Code execangezeigten 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 execund evalfügen Sie das eingebaute Modul __builtins__automatisch zu den Globals hinzu, wenn es fehlt).
In Python 2 execlautet die offizielle Syntax für die Anweisung tatsächlich exec code in globals, localswie 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 execoder evaldurch vorheriges Kompilieren der Quelle in ein codeObjekt zu beschleunigen . Der modeParameter steuert die Art des von der compileFunktion 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 reprdes Wertes dieses Ausdrucks in der Standardausgabe (!) .
Eine if- elif- elseKette, eine Schleife mit elseund trymit seinen except, elseund finallyBlö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 evalden resultierenden Code verwenden.
Die größte Unterscheidung von execund evalkommt tatsächlich von der compileFunktion und ihren Modi.
compileUnterstützt neben dem Kompilieren von Quellcode zu Bytecode auch das Kompilieren abstrakter Syntaxbäume (Analysebäume von Python-Code) in codeObjekte. und Quellcode in abstrakte Syntaxbäume (der ast.parseist 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 evalnur eine Zeichenfolge auswerten können, die einen einzelnen Ausdruck enthält, können Sie evaleine ganze Anweisung oder sogar ein ganzes Modul, das compilein Bytecode umgewandelt wurde, verwenden. Das heißt, mit Python 2 printist eine Anweisung und kann nicht direkt evalgefü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
compilees mit 'exec'Modus in ein codeObjekt und Sie können eval es ; Die evalFunktion 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 evalund execQuellcode in CPython 3, dann ist dies sehr deutlich; Beide rufen PyEval_EvalCodemit denselben Argumenten auf. Der einzige Unterschied besteht darin, dass sie execexplizit zurückgegeben werdenNone .
Syntaxunterschiede execzwischen Python 2 und Python 3
Einer der Hauptunterschiede in Python 2 besteht darin, dass execes sich um eine Anweisung und evaleine integrierte Funktion handelt (beide sind in Python 3 integrierte Funktionen). Es ist eine bekannte Tatsache, dass die offizielle Syntax von execin Python 2 ist exec code [in globals[, locals]].
Im Gegensatz Mehrheit der Python 2-zu-3 - Portierung Führer scheinen vorzuschlagen , die execAussage in CPython 2 kann auch mit Syntax verwendet wird, sieht genau wie der execFunktionsaufruf 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 execAnweisung 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 codeein Tupel der Länge 2 oder 3 war, und globalsund localswurden nicht in die vergangen execsonst Aussage, die codewürde interpretiert werden als ob das zweite und dritte Element des Tupels waren globalsund localssind. 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 execbietet Kompatibilität mit Python 3, wobei execes 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 execeine 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 execin 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 execimmer 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 forstattdessen 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?