Wie führe ich eine Zeichenfolge aus, die Python-Code in Python enthält?
Wie führe ich eine Zeichenfolge aus, die Python-Code in Python enthält?
Antworten:
Verwenden Sie für Anweisungen exec(string)
(Python 2/3) oder exec string
(Python 2):
>>> 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.
if s=='foo': x.foo = 42 elif s=='bar': x.bar = 42
etc, 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) = 42
um dasselbe zu bedeuten.
setattr(x, s, 42)
? Ich habe es versucht getattr(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 , dass getattr
und setattr
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.
import sys
import StringIO
# 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()
exec
(es sei denn, Sie wissen, dass die Codezeichenfolge aus einer vertrauenswürdigen Quelle stammt).
eval
und exec
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:
public_variable = 10
private_variable = 2
def 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' is not 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' is not defined
Im Wesentlichen definieren Sie den Namespace, in dem der Code ausgeführt wird.
eval
oder exec
sollen 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, exec
ist nicht gefährlicher als ein unsicheres Programm, das den Schaden selbst verursacht, da exec
es dem Programm keine neuen Berechtigungen verleiht.
exec
undeval
exec
und eval
in Python ist sehr verpönt.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.
Von Alternativen zu Exec / Eval?
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.Verwenden Sie stattdessen besser ein Diktat.
Von http://lucumr.pocoo.org/2011/2/1/exec-in-python/ (Schwerpunkt Mine)
Python ist kein PHP
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,
exec
heißt das nicht, dass Sie dieses Tool verwenden sollten.
Von http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (Hervorhebung von mir)
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...
Von http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (Hervorhebung von mir):
Erstens
exec
ist 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.
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, reldir
dass diese Literalzeichenfolge nicht ausgewertet wird, sodass ich keine Datei in öffnen kann reldir
. Hast du einen vorschlag
Sie führen die Ausführung von Code mit exec aus, wie in der folgenden IDLE-Sitzung:
>>> kw = {}
>>> exec( "ret = 4" ) in kw
>>> kw['ret']
4
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:
NameError: Der Name 'p_variable' ist nicht definiert
exec('p_variable = [1,2,3,4]')
global p_variable
print(p_variable)
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())
Ich habe einige Dinge ausprobiert, aber das einzige, was funktioniert hat, war das Folgende:
temp_dict = {}
exec("temp_dict['val'] = 10")
print(temp_dict['val'])
Ausgabe:
10
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 = None
try:
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 is not None:
m.apply_address_filter(myobj)
Daher würde customerName = "jj" apply_address_filter aus der Datei customer_filters \ jj_filter.py ausführen