Problem mit exec innerhalb einer Funktion

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
Kartoffel
User
Beiträge: 66
Registriert: Montag 7. April 2003, 17:08

Also, ich habe folgende Funktion:

Code: Alles auswählen

def einlesen(x):
	exec x.widget.get()	
Sie wird ausgeführt, wenn ich einen Text in ein Tkinter-Entry-Feld eingegeben habe und die Return-Taste drücke.
Mein Problem ist folgendes: Der eingegebene Programmcode wird zwar ausgeführt, aber die Variablen, die ich darin definiert habe, gehen verloren, d.h. sie sind nachher nicht mehr vorhanden.
Ich vermute mal, dass es daran liegt, dass die Objekte im Namensraum der Funktion erstellt werden und darum beim Beenden des Funktionsdurchlaufs wieder gelöscht werden.
Ich hab aber keine Ahnung, wie ich das ändern kann, hat jemand ne Idee?
rAiNm4n
User
Beiträge: 19
Registriert: Mittwoch 4. Juni 2003, 11:30
Wohnort: Berlin

Kartoffel hat geschrieben: Ich vermute mal, dass es daran liegt, dass die Objekte im Namensraum der Funktion erstellt werden und darum beim Beenden des Funktionsdurchlaufs wieder gelöscht werden.
Genau, Also musst du die Variablen aus dem lokalen Namensraum der Funktion in den globalen Namesnraum übertragen.

Code: Alles auswählen

import sys

def einlesen(x):
   exec x.widget.get()
   namespace = locals()  # speichert alle lokalen Namen in Form eines Dictionaries in namespace
   for varname in namespace.keys():
      setattr(sys.modules["__main__"], varname, namespace[varname])
   # sys.modules ist ein Dictionary aller Module und __main__ ist immer das Hauptmodul (dein Skript)
Ist zwar etwas umständlich, aber es funktioniert auf jeden Fall...



cu
Chris
bombing for freedom is like fucking for virginity
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hi, eine Globale Variable mit "global" definieren geht auch ;) Nur eine Frage: x.widget.get() ist doch ein Funktionsruf, oder? Wofür brauchst du hier exec? :?:
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Milan hat geschrieben:Nur eine Frage: x.widget.get() ist doch ein Funktionsruf, oder? Wofür brauchst du hier exec? :?:
Nicht get() wird mit exec ausgeführt, sondern das, was get() zurückliefert, also den Inhalt des Entry-Widgets. Ich hab' mal global a; a = 42 eingegeben und nach Return dann print a. Hat funktioniert! Spaßige Sache ;-)
Jan
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Danke Voges, hatte ich glatt vergessen. :roll: Ich glaube aber, das rainmans Lösung besser doch ist, weil ja nicht bekannt ist, wie die gloabale(n) Variablen heißen müssen, sie werden ja dynamisch erzeugt. Man könnte höchstens das machen:

Code: Alles auswählen

def einlesen(x):
    exec x.widget.get()
    global ergebnisse
    ergebnisse=locals()
Jetzt stünden alle Variablen deiner Funktion in ergebnisse (Dictionary!) und sind per Definition auch global nutzbar (also außerhalb deiner Funktion).
Kartoffel
User
Beiträge: 66
Registriert: Montag 7. April 2003, 17:08

Hm, nette Versuche. Inzwischen hab ich aber selbst einen viel einfacheren Weg gefunden:

exec code in globals()

führt den string Code mit globals als globalen und lokalen Namensraum aus.
Ist doch manchmal gut, die mitgelieferte Doku zu lesen, auch wenn sie nicht sehr übersichtlic ist...
Antworten