Berechnung mit exec()-Befehl klappt nicht

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Falkee
User
Beiträge: 5
Registriert: Donnerstag 3. März 2022, 11:52

Hallo zusammen,
ich bin relativ neu im Thema Python, seht es mir also bitte nach, wenn mein Fehler einigermaßen trivial sein sollte XD.

Ich bin arbeite aktuell daran, Formeln automatisiert zu berechnen. Die Formel liegt in Form eines Strings in einem Array vor und soll die benötigten Werte selbstständig aus einem Dictionary abfragen und einfügen. Soweit so gut.
Wenn ich das Ganze so schreibe, (Auszug)

Code: Alles auswählen

daten = {'001' : 5, '002': 10}
Formel = ["a = daten['001'] * daten['002']"]

exec(Formel[0])
print(a)
funktioniert der Code problemlos und ich erhalte als Ausgabe richtigerweise 50.

Wenn ich es aber so schreibe,

Code: Alles auswählen

daten = {'001' : 5, '002': 10}
Formel = ["a = daten['001'] * daten['002']"]

def berechnung():
    exec(Formel[0])
    print(a)

berechnung()
bekomme ich immer einen NameError (name 'a' is not defined) und wenn ich a dann z.B. als null definiere (einfach mit a = 0, der Wert sollte durch die Berechnung ja theoretisch überschrieben werden), erhalte ich 0 egal, wo im Programm ich die Zuweisung hinschreibe.

Kann mir jemand bei diesem Problem helfen?
Ich bin dankbar für jeden Tipp.

Danke schon mal im Voraus
Benutzeravatar
peterpy
User
Beiträge: 188
Registriert: Donnerstag 7. März 2013, 11:35

Hallo Falkee,

die Fehlermeldung sagt es doch, die Variable a ist nicht definiert.

Code: Alles auswählen

def berechnung():
    a = exec(Formel[0])
    print(a)
Gruss Peter
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@peterpy: so gehts nicht. Exec liefert None, egal, was du Darin ausrechnest. Du hast jetzt also einen Namen, aber keinen sinnvollen Wert.

@Falkee sowas ist erstmal ziemlich schlecht, weil exec und sein kleiner Bruder eval horrende sicherheitslücken reißen. Man sollte das also nicht benutzen. Kannst du deine Anforderungen auch anders umsetzen? Bzw Einfluss auf die nehmen?
Falkee
User
Beiträge: 5
Registriert: Donnerstag 3. März 2022, 11:52

Hallo,
danke für die schnellen Antworten.
@__deets__: Ah ok, in die Richtung habe ich gar nicht gedacht, es ergibt aber auf jeden Fall Sinn, wenn ich so darüber nachdenke. Klar, vom Prinzip her könnte man das sicher auch anders umsetzen, exec war nur das Erste, was mir nach ein bisschen Googelei über den Weg gelaufen ist und auch bisher relativ einfach funktioniert hat.
Ziel ist "einfach nur", die Formel mit Variablen zu berechnen. Hättest Du vielleicht eine Idee, wie man das sonst noch umsetzen könnte?

PS: Ich habe gerade schon versucht, den ersten Ansatz, der hier (https://stackoverflow.com/questions/330 ... ing-python) vorgeschlagen wird, zu verwenden, das hat aber leider nicht funktioniert (AttributeError: module 'operator' has no attribute 'div')
Falkee
User
Beiträge: 5
Registriert: Donnerstag 3. März 2022, 11:52

Kleiner Nachtrag:
Ich bin gerade auf diesen Post (viewtopic.php?t=5523) gestoßen.
Dort wird unter anderem vorgeschlagen, den String vor dem Ausführen zu bearbeiten und bestimmte Zeichen wie "." "," etc daraus zu löschen, wenn vorhanden.
Könnte das eine Lösung sein, um das Sicherheitsrisiko zu senken? Der Post ist ja schon etwas älter, deswegen dachte ich, frage ich besser nochmal nach...
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

@Falkee: was ist Dein eigentliches Problem? Was für eine Formel soll da berechnet werden? Woher kommt die? Woher kommen die `daten`?
Benutzeravatar
DeaD_EyE
User
Beiträge: 1244
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Hier eine Lösung die Funktioniert, aber nicht verwendet werden sollte, da gefährlich:

Code: Alles auswählen

daten = {"001": 5, "002": 10}
Formel = ["a = daten['001'] * daten['002']"]


def berechnung():
    env = {"daten": daten}
    exec(Formel[0], env)
    print(env["a"])


berechnung()
Die entschärfte Variante:

Code: Alles auswählen

daten = {"001": 5, "002": 10}
# keine Zuweisung nach a
Formel = ["daten['001'] * daten['002']"]


def berechnung():
    a = eval(Formel[0])
    print(a)


berechnung()

Schreib aber erst mal, was du eigentlich vorhast. Das lässt sich dann einfacher und besser lösen, wenn man den Hintergrund kennt.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Falkee hat geschrieben: Donnerstag 3. März 2022, 13:05 Hallo,
danke für die schnellen Antworten.
@__deets__: Ah ok, in die Richtung habe ich gar nicht gedacht, es ergibt aber auf jeden Fall Sinn, wenn ich so darüber nachdenke. Klar, vom Prinzip her könnte man das sicher auch anders umsetzen, exec war nur das Erste, was mir nach ein bisschen Googelei über den Weg gelaufen ist und auch bisher relativ einfach funktioniert hat.
Ziel ist "einfach nur", die Formel mit Variablen zu berechnen. Hättest Du vielleicht eine Idee, wie man das sonst noch umsetzen könnte?

PS: Ich habe gerade schon versucht, den ersten Ansatz, der hier (https://stackoverflow.com/questions/330 ... ing-python) vorgeschlagen wird, zu verwenden, das hat aber leider nicht funktioniert (AttributeError: module 'operator' has no attribute 'div')
Der Code ist für Python 2. In 3 musst du einen anderen Operator nehmen, zb truediv. Und das ist IMHO einer der besten Ansätze, wenn du den umgesetzt bekommst. Es ist nahezu aussichtslos zu probieren, die Eingabe zu “reinigen”, wie in dem anderen Post.
Falkee
User
Beiträge: 5
Registriert: Donnerstag 3. März 2022, 11:52

@Sirius3 @DeaD_EyE
Sowohl die Formel als auch die Daten stammen aus einer Datenbank und werden automatisiert abgerufen und in die Liste bzw. das Dictionary übertragen. Das klappt soweit auch schon problemlos. Zum aktuellen Stand steht dann die Berechnung als solche an, die die gewonnenen Daten verarbeiten soll.

@__deets__
Super, vielen Dank, das hat geholfen! Jetzt funktioniert es tatsächlich
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum stehen in der Datenbank Formeln? Woher kommen die? Wer hat die da eingetragen? Und warum sind das Python-Ausdrücke?
Falkee
User
Beiträge: 5
Registriert: Donnerstag 3. März 2022, 11:52

Der Datenbank liegt im Prinzip eine Excel-Tabelle zu Grunde, die mit Python berechnet werden soll. Die Formeln sind dazu da, einzelne Werte in Abhängigkeit von anderen zu berechnen. Eingetragen habe ich sie dort und extra so angepasst, dass man sie ohne viel Aufwand in Python verwenden kann
Antworten