Wie führe ich einen String aus, der Python-Code in Python enthält?
Im Beispiel wird ein String 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()
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 wirklich etwas brauchen. Das Ausführen von Code sollte im Allgemeinen die Position des letzten Auswegs sein: Er ist langsam, hässlich und gefährlich, wenn er vom Benutzer eingegebener Code enthalten kann. Sie sollten immer zuerst nach Alternativen suchen, z. B. mit Funktionen höherer Ordnung, um zu sehen, ob diese Ihren Anforderungen besser entsprechen.
Denken Sie daran, dass ab Version 3 exec
eine Funktion ist!
Verwenden Sie also immer exec(mystring)
anstelle von exec mystring
.
eval
und exec
sind die richtige Lösung und können auf sicherere Weise verwendet werden.
Wie in Python's Referenzhandbuch erläutert und in dieses Lernprogramm klar erläutert, benötigen die Funktionen eval
und exec
zwei zusätzliche Parameter, mit denen ein Benutzer angeben kann, welche globalen und lokalen Funktionen und Variablen verfügbar sind.
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()
ist nur für Ausdrücke, während eval('x+1')
funktioniert, eval('x=1')
zum Beispiel nicht funktioniert. In diesem Fall ist es besser, exec
zu verwenden, oder noch besser: Versuchen Sie, eine bessere Lösung zu finden :)
Sie führen die Ausführung von Code mithilfe von exec wie bei der folgenden IDLE-Sitzung aus:
>>> kw = {}
>>> exec( "ret = 4" ) in kw
>>> kw['ret']
4
exec
und eval
exec
und eval
in Python ist äußerst verpönt.Von der obersten Antwort (Hervorhebung meines):
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 wirklich etwas brauchen. Ausführungscode sollte im Allgemeinen die Position des letzten Auswegs sein: Es ist langsam, hässlich und gefährlich, wenn er vom Benutzer eingegebenen Code enthalten kann. Sie sollten immer zuerst alternatives betrachten, z. B. Funktionen höherer Ordnung, um zu sehen, ob diese Ihren Anforderungen besser entsprechen.
Von Alternativen zu exec/eval?
setze und erhalte Werte von Variablen mit den Namen in Strings
[Während
eval
] funktionieren würde, wird generell davon abgeraten, Variablennamen zu verwenden, die eine Bedeutung für das Programm selbst haben.Verwenden Sie stattdessen lieber ein Dikt.
Von http://lucumr.pocoo.org/2011/2/1/exec-in-python/ (Hervorhebung meines)
Python ist kein PHP
Versuchen Sie nicht, Python-Idiome zu umgehen, da eine andere Sprache dies anders macht. Namespaces sind aus einem bestimmten Grund in Python und , nur weil es das Werkzeug
exec
gibt, bedeutet dies nicht, dass Sie dieses Werkzeug verwenden sollten.
Von http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (Hervorhebung meines)
Eval ist also nicht sicher, auch wenn Sie alle Globals und die 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 eine Niederlage, weil wenn nur ein Element von der Liste übrig ist, können Sie das System angreifen.
Kann also eval sicher gemacht werden? Schwer zu sagen. Meine beste Vermutung ist an diesem Punkt, dass Sie keinen Schaden anrichten können, wenn Sie keine doppelten Unterstriche verwenden können. Wenn Sie also eine Zeichenfolge mit doppelten Unterstrichen ausschließen, sind Sie sicher. Könnte sein...
Von http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (Hervorhebung meines):
Zunächst macht es
exec
für Menschen schwieriger, Ihren Code zu lesen. Um herauszufinden, was passiert, muss ich nicht nur Ihren Code lesen, Ich muss Ihren Code lesen, herausfinden, welche Zeichenfolge er erzeugen wird, und dann den virtuellen Code lesen. Wenn Sie also in einem Team arbeiten, Open-Source-Software veröffentlichen oder an einem anderen Ort wie StackOverflow um Hilfe bitten, ist es für andere schwieriger, Ihnen zu helfen. Und wenn Sie die Möglichkeit haben, diesen Code in 6 Monaten zu debuggen oder zu erweitern, wird es für Sie direkt schwieriger.
Check out Bewertung :
x = 1
print eval('x+1')
->2
Die logischste Lösung wäre die Verwendung der integrierten Funktion eval () . Eine andere Lösung besteht darin, diesen String in eine temporäre Python-Datei zu schreiben und auszuführen.
Verwenden Sie eval .
Es ist erwähnenswert, dass der Bruder von 'exec
auch execfile
heißt, wenn Sie eine python Datei aufrufen möchten. Das ist manchmal gut, wenn Sie in arbeiten ein Paket von Drittanbietern, in dem schreckliche IDEs enthalten sind und das Sie außerhalb des Pakets codieren möchten.
Beispiel:
execfile('/path/to/source.py)'
oder:
exec(open("/path/to/source.py").read())
Wie die anderen erwähnt haben, ist es "exec" ..
falls Ihr Code jedoch Variablen enthält, können Sie "global" verwenden, um darauf zuzugreifen, und verhindern, dass der Compiler den folgenden Fehler ausgibt:
NameError: Name 'p_variable' ist nicht definiert
exec('p_variable = [1,2,3,4]')
global p_variable
print(p_variable)
Ok .. Ich weiß, das ist nicht genau eine Antwort, aber möglicherweise eine Notiz für Leute, die sich das so ansehen, wie ich es war. Ich wollte spezifischen Code für verschiedene Benutzer/Kunden ausführen, aber auch die Exec/Eval vermeiden. Ich habe zunächst versucht, den Code für jeden Benutzer in einer Datenbank zu speichern und dies zu tun.
Am Ende habe ich die Dateien im Dateisystem in einem 'customer_filters'-Ordner erstellt und das' imp'-Modul verwendet. Wenn für diesen Kunden kein Filter angewendet wurde, wurde er einfach weitergeführt
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)
customerName = "jj" führt dann apply_address_filter aus der Datei customer_filters\jj_filter.py aus