Um fair zu sein, ist diese Frage im Gegensatz zur anderen Frage kein Duplikat. Und andere haben viel grundlegendere Fragen gestellt.
DNS
8
Die richtige Antwort lautet natürlich fast immer „nicht!“.
Bobince
23
@S. Lott: Hast du die FAQ in letzter Zeit nicht gelesen? "Es ist auch vollkommen in Ordnung, Ihre eigene Programmierfrage zu stellen und zu beantworten, aber tun Sie so, als wären Sie in Gefahr: Formulieren Sie sie in Form einer Frage." Das ist keine schlechte Frage. +1
Devin Jeanpierre
49
@ S.Lott: Das tust du nicht. Das musst du nicht. Wenn die Frage noch nicht auf der Website ist, handelt es sich um ein faires Spiel (laut FAQ, wie bereits erwähnt). Beantworten Sie einfach jede Frage, als ob das OP Hilfe benötigt. Sie mögen es nicht, aber der nächste, der ihre Frage liest, wird es wahrscheinlich tun. Nur meine 2 Cent.
Bill the Lizard
1
An alle, die sagen, dass Sie es nicht tun sollen: Ich habe einen Fall, in dem ich es unbedingt muss. Es handelt sich um eine verteilte Verarbeitung.
>>> mycode ='print "hello world"'>>>exec(mycode)Hello world
Wenn Sie den Wert eines Ausdrucks benötigen, verwenden Sie eval(string):
>>> x = eval("2+2")>>> x
4
Der erste Schritt sollte jedoch sein, sich zu fragen, ob Sie es wirklich brauchen. Das Ausführen von Code sollte im Allgemeinen die letzte Instanz sein: Es ist langsam, hässlich und gefährlich, wenn es vom Benutzer eingegebenen Code enthalten kann. Sie sollten immer zuerst nach Alternativen suchen, z. B. nach Funktionen höherer Ordnung, um festzustellen, ob diese Ihren Anforderungen besser entsprechen können.
aber wie steht es mit dem Umfang des von 'exec' ausgeführten Codes? ist es verschachtelt?
Jondinham
21
Ein häufiger Fall, in dem jemand 'exec' verwenden möchte, ist so etwas wie if s=='foo': x.foo = 42 elif s=='bar': x.bar = 42etc, als das er dann schreiben kann exec ("x.%s = 42" % s). In diesem häufigen Fall (in dem Sie nur auf das Attribut eines Objekts zugreifen müssen, das in einer Zeichenfolge gespeichert ist) gibt es eine viel schnellere, sauberere und sicherere Funktion getattr: Schreiben Sie einfach, getattr(x, s) = 42um dasselbe zu bedeuten.
ShreevatsaR
5
Wie ist exec langsamer als der Python-Interpreter?
Cris Stringfellow
6
@ShreevatsaR meinst du nicht setattr(x, s, 42)? Ich habe es versucht getattr(x, 2) = 42und es ist fehlgeschlagen mitcan't assign to function call: <string>, line 1
Tanner Semerad
6
@ Gerber: Hmm. Ja, in der Tat setattr(x, s, 42)ist die richtige Syntax. Überrascht dauerte es so lange, bis dieser Fehler erkannt wurde. Wie auch immer, der Punkt ist , dass getattrund setattrist eine Alternative zu , execwenn alles , was Sie wollen , ist ein beliebiges Mitglied zu bekommen, sah durch Zeichenfolge auf.
ShreevatsaR
68
Im Beispiel wird eine Zeichenfolge mit der Funktion exec als Code ausgeführt.
import sys
importStringIO# create file-like string to capture output
codeOut =StringIO.StringIO()
codeErr =StringIO.StringIO()
code ="""
def f(x):
x = x + 1
return x
print 'This is my output.'
"""# capture output and errors
sys.stdout = codeOut
sys.stderr = codeErr
exec code
# restore stdout and stderr
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
print f(4)
s = codeErr.getvalue()print"error:\n%s\n"% s
s = codeOut.getvalue()print"output:\n%s"% s
codeOut.close()
codeErr.close()
stdout und stderr so auszutauschen macht mich sehr nervös. Dies scheint große Sicherheitsprobleme zu verursachen. Gibt es einen Weg, das zu umgehen?
Narcolapser
1
@Narcolapser Sie sollten sich mehr mit der Verwendung befassen exec(es sei denn, Sie wissen, dass die Codezeichenfolge aus einer vertrauenswürdigen Quelle stammt).
Bruno Desthuilliers
27
evalund execsind die richtige Lösung, und sie können sicherer verwendet werden werden.
Wie im Referenzhandbuch von Python erläutert und in diesem Lernprogramm klar erläutert , werden die evalundexec nehmen Funktionen zwei zusätzliche Parameter , die ein Benutzer angeben lassen , was globale und lokale Funktionen und Variablen zur Verfügung stehen.
Zum Beispiel:
public_variable =10
private_variable =2def public_function():return"public information"def private_function():return"super sensitive information"# make a list of safe functions
safe_list =['public_variable','public_function']
safe_dict = dict([(k, locals().get(k,None))for k in safe_list ])# add any needed builtins back in
safe_dict['len']= len
>>> eval("public_variable+2",{"__builtins__":None}, safe_dict)12>>> eval("private_variable+2",{"__builtins__":None}, safe_dict)Traceback(most recent call last):File"<stdin>", line 1,in<module>File"<string>", line 1,in<module>NameError: name 'private_variable'isnot defined
>>>exec("print \"'%s' has %i characters\" % (public_function(), len(public_function()))",{"__builtins__":None}, safe_dict)'public information' has 18 characters
>>>exec("print \"'%s' has %i characters\" % (private_function(), len(private_function()))",{"__builtins__":None}, safe_dict)Traceback(most recent call last):File"<stdin>", line 1,in<module>File"<string>", line 1,in<module>NameError: name 'private_function'isnot defined
Im Wesentlichen definieren Sie den Namespace, in dem der Code ausgeführt wird.
Es ist nicht möglich, eval sicher zu machen: Eval ist wirklich gefährlich . Wenn Sie Code von mir nehmen und bewerten, kann ich Ihr Python-Programm fehlerhaft ausführen. Spiel ist aus.
Ned Batchelder
3
@ v.oddou Ich antwortete auf Alan's Aussage: "eval und exec .. können auf sichere Weise verwendet werden." Das ist falsch. Wenn jemand sagte, "Bash kann auf sichere Weise verwendet werden", wäre das auch falsch. Bash ist gefährlich. Es ist eine notwendige Gefahr, aber dennoch gefährlich. Die Behauptung, dass Eval sicher gemacht werden kann, ist einfach falsch.
Ned Batchelder
1
@NedBatchelder ja in der Tat. und der Link, auf den Sie verweisen, ist gutes Material. Mit der Macht geht die Verantwortung einher, daher geht es einfach darum, sich der potenziellen Macht der Bewertung bewusst zu sein. und wenn wir entscheiden, dass Macht = Gefahr.
v.oddou
3
@NedBatchelder Viele in Python geschriebene Codeteile können ebenfalls gefährlich sein, aber warum nehmen Sie das an evaloder execsollen als verwendet werden exec(input("Type what you want"))? Es gibt viele Fälle, in denen ein Programm als Ergebnis einer Berechnung eine Prozedur oder eine Funktion schreiben kann. Die resultierenden Funktionen sind so sicher und schnell (einmal evaluiert) wie jeder andere Teil eines guten und gut geschriebenen Programms. Ein unsicheres Programm, das enthält, execist nicht gefährlicher als ein unsicheres Programm, das den Schaden selbst verursacht, da execes dem Programm keine neuen Berechtigungen verleiht.
Thomas Baruchel
1
@ThomasBaruchel noch einmal, mein Punkt ist es, der Vorstellung entgegenzuwirken, dass eval oder exec sicher gemacht werden können. Diese Antwort behauptet insbesondere, dass die Kontrolle der Globalen und Einheimischen es ermöglichen wird, sie sicher zu verwenden. Das ist falsch. Jedes Mal, wenn Sie exec und eval verwenden, müssen Sie genau wissen, welcher Code ausgeführt wird. Wenn Sie dies nicht tun, sind Sie offen für gefährliche Operationen.
Ned Batchelder
21
Denken Sie daran, dass ab Version 3 execeine Funktion ist!
also immer exec(mystring)anstelle von verwenden exec mystring.
eval()ist nur für Ausdrücke, während es eval('x+1')funktioniert, eval('x=1')funktioniert es zum Beispiel nicht. In diesem Fall ist es besser zu verwenden execoder noch besser: versuchen Sie eine bessere Lösung zu finden :)
Die Verwendung von execund evalin Python ist sehr verpönt.
Es gibt bessere Alternativen
Von der obersten Antwort (Hervorhebung meiner):
Verwenden Sie für Anweisungen exec.
Wenn Sie den Wert eines Ausdrucks benötigen, verwenden Sie eval.
Der erste Schritt sollte jedoch sein, sich zu fragen, ob Sie es wirklich brauchen. Das Ausführen von Code sollte im Allgemeinen die letzte Instanz sein : Es ist langsam, hässlich und gefährlich, wenn es vom Benutzer eingegebenen Code enthalten kann. Sie sollten immer zuerst nach Alternativen suchen , z. B. nach Funktionen höherer Ordnung , um festzustellen, ob diese Ihren Anforderungen besser entsprechen können.
Setzen und Abrufen von Variablenwerten mit den Namen in Zeichenfolgen
[während eval ] würde funktionieren, es wird im Allgemeinen nicht empfohlen, Variablennamen zu verwenden, die für das Programm selbst eine Bedeutung haben.
Versuchen Sie nicht, Python-Redewendungen zu umgehen, da dies in einer anderen Sprache anders ist. Namespaces befinden sich aus einem bestimmten Grund in Python. Nur weil Sie das Tool erhalten, execheißt das nicht, dass Sie dieses Tool verwenden sollten.
Eval ist also nicht sicher, selbst wenn Sie alle Globals und Builtins entfernen!
Das Problem bei all diesen Versuchen, eval () zu schützen, ist, dass es sich um schwarze Listen handelt . Sie entfernen explizit Dinge, die gefährlich sein könnten. Das ist ein verlorener Kampf, denn wenn nur noch ein Gegenstand von der Liste übrig ist, können Sie das System angreifen .
Kann eval also sicher gemacht werden? Schwer zu sagen. An dieser Stelle gehe ich davon aus, dass Sie keinen Schaden anrichten können, wenn Sie keine doppelten Unterstriche verwenden können. Wenn Sie also einen String mit doppelten Unterstrichen ausschließen, sind Sie sicher. Könnte sein...
Erstens execist es für Menschen schwieriger, Ihren Code zu lesen . Um herauszufinden, was passiert, muss ich nicht nur Ihren Code lesen, sondern auch Ihren Code lesen, herausfinden, welche Zeichenfolge generiert wird, und dann diesen virtuellen Code lesen. Wenn Sie also in einem Team arbeiten, Open Source-Software veröffentlichen oder irgendwo wie StackOverflow um Hilfe bitten, erschweren Sie es anderen, Ihnen zu helfen. Und wenn es eine Chance gibt, dass Sie diesen Code in 6 Monaten debuggen oder erweitern, machen Sie es sich direkt schwerer.
"Meine beste Vermutung ist, dass Sie keinen Schaden anrichten können, wenn Sie keine doppelten Unterstriche verwenden können." - Sie könnten eine Zeichenfolge mit doppelten Unterstrichen erstellen und diese Zeichenfolge dann eval aufrufen.
Stanley Bak
Guter Rat, es sei denn, Sie schreiben einen Codegenerator, einen Job Runner oder ähnliches ... was die meisten Leute hier wahrscheinlich tun.
Erik Aronesty
Ich muss einen relativen Pfad aus einer Konfigurationsdatei ( cfg.yaml) importieren:, reldir : ../my/dir/ und reldir = cfg[reldir]. Da dieser Python-Code jedoch sowohl unter Windows als auch unter Linux ausgeführt werden soll, muss er an die verschiedenen Pfadteiler der Betriebssysteme angepasst werden. entweder \\ oder /. Also benutze ich reldir : os.path.join('..','my','dir')in der Konfigurationsdatei. Dies führt jedoch nur dazu, reldirdass diese Literalzeichenfolge nicht ausgewertet wird, sodass ich keine Datei in öffnen kann reldir. Hast du einen vorschlag
Marie. P.
9
Sie führen die Ausführung von Code mit exec aus, wie in der folgenden IDLE-Sitzung:
Es ist erwähnenswert, dass der execBruder auch so genannt wirdexecfile wenn Sie eine Python-Datei aufrufen möchten. Das ist manchmal gut, wenn Sie in einem Paket eines Drittanbieters arbeiten, in dem schreckliche IDEs enthalten sind, und wenn Sie außerhalb des Pakets codieren möchten.
Die logischste Lösung wäre die Verwendung der integrierten Funktion eval (). Eine andere Lösung besteht darin, diese Zeichenfolge in eine temporäre Python-Datei zu schreiben und auszuführen.
Ok .. Ich weiß, das ist nicht gerade eine Antwort, aber möglicherweise eine Notiz für Leute, die das so sehen wie ich. Ich wollte spezifischen Code für verschiedene Benutzer / Kunden ausführen, aber auch die Ausführung / Auswertung vermeiden. Ich habe zunächst versucht, den Code für jeden Benutzer in einer Datenbank zu speichern und die oben genannten Schritte auszuführen.
Am Ende habe ich die Dateien im Dateisystem in einem Ordner 'customer_filters' erstellt und das Modul 'imp' verwendet. Wenn für diesen Kunden kein Filter angewendet wurde, wurde es einfach fortgesetzt
import imp
def get_customer_module(customerName='default', name='filter'):
lm =Nonetry:
module_name = customerName+"_"+name;
m = imp.find_module(module_name,['customer_filters'])
lm = imp.load_module(module_name, m[0], m[1], m[2])except:''#ignore, if no module is found, return lm
m = get_customer_module(customerName,"filter")if m isnotNone:
m.apply_address_filter(myobj)
Daher würde customerName = "jj" apply_address_filter aus der Datei customer_filters \ jj_filter.py ausführen
Antworten:
Verwenden Sie für Anweisungen
exec(string)
(Python 2/3) oderexec string
(Python 2):Wenn Sie den Wert eines Ausdrucks benötigen, verwenden Sie
eval(string)
:Der erste Schritt sollte jedoch sein, sich zu fragen, ob Sie es wirklich brauchen. Das Ausführen von Code sollte im Allgemeinen die letzte Instanz sein: Es ist langsam, hässlich und gefährlich, wenn es vom Benutzer eingegebenen Code enthalten kann. Sie sollten immer zuerst nach Alternativen suchen, z. B. nach Funktionen höherer Ordnung, um festzustellen, ob diese Ihren Anforderungen besser entsprechen können.
quelle
if s=='foo': x.foo = 42 elif s=='bar': x.bar = 42
etc, als das er dann schreiben kannexec ("x.%s = 42" % s)
. In diesem häufigen Fall (in dem Sie nur auf das Attribut eines Objekts zugreifen müssen, das in einer Zeichenfolge gespeichert ist) gibt es eine viel schnellere, sauberere und sicherere Funktiongetattr
: Schreiben Sie einfach,getattr(x, s) = 42
um dasselbe zu bedeuten.setattr(x, s, 42)
? Ich habe es versuchtgetattr(x, 2) = 42
und es ist fehlgeschlagen mitcan't assign to function call: <string>, line 1
setattr(x, s, 42)
ist die richtige Syntax. Überrascht dauerte es so lange, bis dieser Fehler erkannt wurde. Wie auch immer, der Punkt ist , dassgetattr
undsetattr
ist eine Alternative zu ,exec
wenn alles , was Sie wollen , ist ein beliebiges Mitglied zu bekommen, sah durch Zeichenfolge auf.Im Beispiel wird eine Zeichenfolge mit der Funktion exec als Code ausgeführt.
quelle
exec
(es sei denn, Sie wissen, dass die Codezeichenfolge aus einer vertrauenswürdigen Quelle stammt).eval
undexec
sind die richtige Lösung, und sie können sicherer verwendet werden werden.Wie im Referenzhandbuch von Python erläutert und in diesem Lernprogramm klar erläutert , werden die
eval
undexec
nehmen Funktionen zwei zusätzliche Parameter , die ein Benutzer angeben lassen , was globale und lokale Funktionen und Variablen zur Verfügung stehen.Zum Beispiel:
Im Wesentlichen definieren Sie den Namespace, in dem der Code ausgeführt wird.
quelle
eval
oderexec
sollen als verwendet werdenexec(input("Type what you want"))
? Es gibt viele Fälle, in denen ein Programm als Ergebnis einer Berechnung eine Prozedur oder eine Funktion schreiben kann. Die resultierenden Funktionen sind so sicher und schnell (einmal evaluiert) wie jeder andere Teil eines guten und gut geschriebenen Programms. Ein unsicheres Programm, das enthält,exec
ist nicht gefährlicher als ein unsicheres Programm, das den Schaden selbst verursacht, daexec
es dem Programm keine neuen Berechtigungen verleiht.Denken Sie daran, dass ab Version 3
exec
eine Funktion ist!also immer
exec(mystring)
anstelle von verwendenexec mystring
.quelle
eval()
ist nur für Ausdrücke, während eseval('x+1')
funktioniert,eval('x=1')
funktioniert es zum Beispiel nicht. In diesem Fall ist es besser zu verwendenexec
oder noch besser: versuchen Sie eine bessere Lösung zu finden :)quelle
Vermeiden Sie
exec
undeval
Die Verwendung von
exec
undeval
in Python ist sehr verpönt.Es gibt bessere Alternativen
Von der obersten Antwort (Hervorhebung meiner):
Von Alternativen zu Exec / Eval?
Es ist nicht idiomatisch
Von http://lucumr.pocoo.org/2011/2/1/exec-in-python/ (Schwerpunkt Mine)
Es ist gefährlich
Von http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (Hervorhebung von mir)
Es ist schwer zu lesen und zu verstehen
Von http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (Hervorhebung von mir):
quelle
cfg.yaml
) importieren:,reldir : ../my/dir/
undreldir = cfg[reldir]
. Da dieser Python-Code jedoch sowohl unter Windows als auch unter Linux ausgeführt werden soll, muss er an die verschiedenen Pfadteiler der Betriebssysteme angepasst werden. entweder\\
oder/
. Also benutze ichreldir : os.path.join('..','my','dir')
in der Konfigurationsdatei. Dies führt jedoch nur dazu,reldir
dass diese Literalzeichenfolge nicht ausgewertet wird, sodass ich keine Datei in öffnen kannreldir
. Hast du einen vorschlagSie führen die Ausführung von Code mit exec aus, wie in der folgenden IDLE-Sitzung:
quelle
Wie die anderen erwähnten, ist es "exec" ..
Falls Ihr Code jedoch Variablen enthält, können Sie mit "global" darauf zugreifen, um zu verhindern, dass der Compiler den folgenden Fehler auslöst:
quelle
Verwenden Sie eval .
quelle
Es ist erwähnenswert, dass der
exec
Bruder auch so genannt wirdexecfile
wenn Sie eine Python-Datei aufrufen möchten. Das ist manchmal gut, wenn Sie in einem Paket eines Drittanbieters arbeiten, in dem schreckliche IDEs enthalten sind, und wenn Sie außerhalb des Pakets codieren möchten.Beispiel:
execfile('/path/to/source.py)'
oder:
exec(open("/path/to/source.py").read())
quelle
Check out eval :
quelle
Ich habe einige Dinge ausprobiert, aber das einzige, was funktioniert hat, war das Folgende:
Ausgabe:
10
quelle
Die logischste Lösung wäre die Verwendung der integrierten Funktion eval (). Eine andere Lösung besteht darin, diese Zeichenfolge in eine temporäre Python-Datei zu schreiben und auszuführen.
quelle
Ok .. Ich weiß, das ist nicht gerade eine Antwort, aber möglicherweise eine Notiz für Leute, die das so sehen wie ich. Ich wollte spezifischen Code für verschiedene Benutzer / Kunden ausführen, aber auch die Ausführung / Auswertung vermeiden. Ich habe zunächst versucht, den Code für jeden Benutzer in einer Datenbank zu speichern und die oben genannten Schritte auszuführen.
Am Ende habe ich die Dateien im Dateisystem in einem Ordner 'customer_filters' erstellt und das Modul 'imp' verwendet. Wenn für diesen Kunden kein Filter angewendet wurde, wurde es einfach fortgesetzt
Daher würde customerName = "jj" apply_address_filter aus der Datei customer_filters \ jj_filter.py ausführen
quelle