Seite 1 von 1

exec() im lokalen Kontext

Verfasst: Donnerstag 9. Juni 2016, 22:50
von Imaginärteil
Ich benötige in einer meiner Arbeiten exec(), um eins als String gespeicherte Liste in ein Programm einfach einlesen zu können.
Bin wegen folgendem Problem noch auf der Suche nach einer vernünftigen Alternative:

In der Dokumentation von exec() (so sagt es jedenfalls IDLE) wird der lokale Kontext berücksichtigt.
Entweder habe ich das komplett falsch verstanden, falsch geschrieben oder er macht es falsch:

Code: Alles auswählen

def f():
    x = 0
    exec("x = 1")
    return x
Nun, das führt von einer Ausgabe von 0, nicht von einer 1, deren Auswurf für mich eigentlich erwartbarer wäre.
Ich habe ein bisschen rumgesucht, was das angeht, bin aber nicht so schlau draus geworden ...

Bisher hat bei mir exec nur in globalem Kontext funktioniert.
Beispiel:

Code: Alles auswählen

x = 0
exec("x = 1")
print(x)
Führt zu 1. Keine Überraschung, das sollte es auch tun. Steht ja auch nicht in einer Funktion.

Trotzdem funktioniert auch folgendes nicht wie erwartet:

Code: Alles auswählen

x = 2
def f():
    global x
    exec("x = 1")
    return x
Was ich daraus schlussfolgere, ist, dass das Schreiben von exec in definierten Funktionen keinen Sinn macht, weil es nicht das tut, was die "File Scope" dort machen würde.

Sollte es an der Indentation liegen, weiß ich bei Himmel nicht, wie ich die im in exec() einzugebenden String verwirklichen soll.

Belehrt mich eines Besseren! :D

Re: exec() im lokalen Kontext

Verfasst: Donnerstag 9. Juni 2016, 23:18
von Sirius3
@Imaginärteil: warum hast Du eine als String gespeicherte Liste? Da ist schon der Fehler. Nimm ein passendes Format, um Listen zu speichern, z.B. JSON.

Re: exec() im lokalen Kontext

Verfasst: Donnerstag 9. Juni 2016, 23:37
von DasIch
Imaginärteil hat geschrieben:Ich benötige in einer meiner Arbeiten exec(), um eins als String gespeicherte Liste in ein Programm einfach einlesen zu können.
Nein brauchst du nicht. Es gibt wesentlich bessere Möglichkeiten Strings zu parsen und wesentlich bessere Möglichkeiten Listen zu serialisieren. Am besten du vergisst dass exec existiert und bei der Gelegenheit vergiss global gleich mit.

Die Dokumentation hat übrigens folgendes zu sagen:
exec() hat geschrieben:Note: The default locals act as described for function locals() below: modifications to the default locals dictionary should not be attempted. Pass an explicit locals dictionary if you need to see effects of the code on locals after function exec() returns.
locals() hat geschrieben:Note: The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
Der Code tut also genau dass was man erwarten würde. exec() führt Code zwar im selben Scope aus aber in einem eigenen Frame wie bei einem Funktionsaufruf, was nicht weniger überraschend ist weil exec() selbst eine Funktion ist.