Seite 1 von 1

Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 21:21
von Alfons Mittelmeyer
Das Problem bei eval oder exec ist, dass Definitionen dort global sind und nicht lokal.

Um Definitionen wieder zu beseitigen, habe ich zwei Lösungen gefunden. Die eine wäre eine modifiziertes read().
Wenn man von einem File liest, könnte man die Zeilen einzeln lesen und dann jede Zeile um vier Leerzeichen oder einen Tab einrücken.
Und eine vorgeschaltete erste Zeile könnte dann den Beginn einer Funktionsdefinition enthalten, etwa:

Code: Alles auswählen

def function() 
Dumm dabei ist, wenn in dem File """ vorkommt. Die nachfolgenden Zeilen dürfte man dann nicht einrücken.
Das wäre die eine Lösung, damit man nur lokale Defintionen bekommt, außer natürlich "function"

Die andere Lösung wäre, dass man globale Definitionen in Kauf nimmt und sie dann rauswirft. Aber so etwas gefällt hier wohl niemand:

Code: Alles auswählen

def clean_eval(evcode):
    glob_before = globals().keys()
    eval(evcode)
    glob_after = globals().keys()
    for element in glob_after:
        if element not in glob_before: del globals()[element]
Sollte man dann die erste Lösung implementieren?
Auch eine Lösung wäre natürlich, gleich in den Scripts, die man lädt, diese Funktionsdefinition am Anfang zu machen. Also Lösung Nummer 3

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 21:28
von BlackJack
@Alfons Mittelmeyer: Am besten und einfachsten man verwendet kein `eval()` oder ``exec`` und wenn man das tut, dann gibt man halt ein Wörterbuch für den globalen Namensraum an statt sich den tatsächlichen Modulnamensraum vollmüllen zu lassen. Dann muss man aus dem hinterher auch nichts entfernen. Vor allem entfernt Dein `clean_eval()` ja nur *neue* Namen, aber was ist wenn der ausgeführte Code vorher vorhandene Namen neu bindet? Wenn er `globals` oder `glob_before` neu bindet, dann fällt `clean_eval()` auch gleich beim Aufräumen auf die Nase.

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 21:39
von Alfons Mittelmeyer
BlackJack hat geschrieben:@Alfons Mittelmeyer: Am besten und einfachsten man verwendet kein `eval()` oder ``exec`` und wenn man das tut, dann gibt man halt ein Wörterbuch für den globalen Namensraum an statt sich den tatsächlichen Modulnamensraum vollmüllen zu lassen. Dann muss man aus dem hinterher auch nichts entfernen. Vor allem entfernt Dein `clean_eval()` ja nur *neue* Namen, aber was ist wenn der ausgeführte Code vorher vorhandene Namen neu bindet? Wenn er `globals` oder `glob_before` neu bindet, dann fällt `clean_eval()` auch gleich beim Aufräumen auf die Nase.
Das mit dem Wörterbuch habe ich nicht ganz verstanden. Zuerst hatte ich {} probiert. Aber da war dann der Zugriff auf tkinter nicht da. Dann hatte ich in den Scripts "from tkinter import *" eingebunden. Da war dann er Zugriff da. Aber das Rauslöschen danach war keine gute Idee.

Ich habe jetzt eine andere Idee. Ich könnte ja an den Beginn eines jeden Scripts für DynTkInter schreiben:

Code: Alles auswählen

def main(parent):
Für DynTkInter brauche ich zwar keinen Parent. Aber dann könnte man auch tkinter Scripts einbinden. Nach Reinladen ruft man dann für das Script einfach main mit dem jeweiligen Parent auf. Gute Idee?

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 21:51
von BlackJack
@Alfons Mittelmeyer: Sowohl bei `eval()` als auch bei ``exec`` kann man optional ein Wörterbuch angeben das dann den Namensraum bildet in dem der Code ausgeführt wird. *Das* sollte man machen damit man sich nicht das Modul zerschiessen kann in dem die Funktion/Anweisung ausgeführt wird die den Code ausführt.

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 21:51
von Sirius3
@Alfons Mittelmeyer: natürlich muß jedes Modul selbst konsistent sein, das heißt, alle externen Namen müssen auch importiert werden. Und wenn man explizit einen globalen Namensraum angibt, braucht man auch nichts aufräumen. Aber Du solltest Dir die Idee mit dem eval wirklich nochmal überdenken.

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 21:54
von Alfons Mittelmeyer
Sirius3 hat geschrieben:@Alfons Mittelmeyer: natürlich muß jedes Modul selbst konsistent sein, das heißt, alle externen Namen müssen auch importiert werden. Und wenn man explizit einen globalen Namensraum angibt, braucht man auch nichts aufräumen. Aber Du solltest Dir die Idee mit dem eval wirklich nochmal überdenken.
Ich denke, dass das mit der Funktion main nicht schlecht ist. Dann brauch ich auch nichts aufräumen, weil dann alles loka ist und main benutzt man sowieso immer. Ständig imp.reload zu machen für Scripte die nur die Funktion main haben, kann ich mir ja noch überlegen.

Ob ich das dann mache, Scripte nach main.py kopieren und dann einen imp.reload für main.py? Kann ja darüber nachdenken. Und dann nach dem reload immer main.main(parent) aufrufen. Und dieser Aufruf sorgt dann dafür, dass weitere solche reloads stattfinden.

Müsste man mal testen, was passiert, wenn main.main(parent) noch nicht abgearbeitet ist und unterdessen das modul reloaded wird.

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 21:55
von snafu
Warum können eigentlich diese Skripte, von denen du immer redest, nicht einfach in einem separatem Interpreter-Prozess laufen (``python dein_skript.py``)? Das wurde dir ja (nicht nur von mir) bereits vorgeschlagen. Was spricht gegen diese Lösung?

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 22:01
von Alfons Mittelmeyer
snafu hat geschrieben:Warum können eigentlich diese Skripte, von denen du immer redest, nicht einfach in einem separatem Interpreter-Prozess laufen (``python dein_skript.py``)? Das wurde dir ja (nicht nur von mir) bereits vorgeschlagen. Was spricht gegen diese Lösung?
Also wie geht das? Starten kann man mit 'python dein_skript.py'. Und wie lade ich dann das nächste Script nach? Angenommen, das Script baut die oberste Gui Ebene auf und die folgenden Scripte sollen dann Frames mit Inhalten füllen?

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 22:17
von BlackJack
``main.main(parent)`` um dann das nächste Modul zu laden und dort `main()` aufzurufen klingt nicht gut, das kracht irgendwann wegen Rekursionslimit. Und es bleibt dann auch immer alles von jeder `main()` aus erreichbare im Speicher solange bis die ganzen Aufrufe dann am Ende hoffentlich mal zum Aufrufer zurückkehren.

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 22:22
von Alfons Mittelmeyer
BlackJack hat geschrieben:``main.main(parent)`` um dann das nächste Modul zu laden und dort `main()` aufzurufen klingt nicht gut, das kracht irgendwann wegen Rekursionslimit. Und es bleibt dann auch immer alles von jeder `main()` aus erreichbare im Speicher solange bis die ganzen Aufrufe dann am Ende hoffentlich mal zum Aufrufer zurückkehren.
Naja, mehr wie sechs Ebenen dürfte auch ein komplexe GUI nicht haben. Und direkt Rekursion wäre es nicht, weil das ja dann ein anderes main() wäre.

Ich kann es statt compile und eval dann auch mal mit imp.reload versuchen, ob das ebenso funktioniert.

Allerdings umständlich ist es schon. Es gibt auch ein paar Fälle, wo ich files reinlese und modifiziere. Wenn ich, anstatt sie gleich danach zu kompilieren und auszuführen nochmals abspeichern und reloaden soll.

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 22:26
von DasIch
Alfons Mittelmeyer hat geschrieben:
snafu hat geschrieben:Warum können eigentlich diese Skripte, von denen du immer redest, nicht einfach in einem separatem Interpreter-Prozess laufen (``python dein_skript.py``)? Das wurde dir ja (nicht nur von mir) bereits vorgeschlagen. Was spricht gegen diese Lösung?
Also wie geht das? Starten kann man mit 'python dein_skript.py'. Und wie lade ich dann das nächste Script nach? Angenommen, das Script baut die oberste Gui Ebene auf und die folgenden Scripte sollen dann Frames mit Inhalten füllen?
Kann es sein dass du ein Pluginsystem suchst?

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 22:26
von snafu
Die Frage war ja nach dem "Warum". Mir war bisher nicht klar, wozu diese Skripte überhaupt dienen sollen.

Wenn sie am Aufbau der GUI beteiligt sein sollen, warum können sie dann nicht einfach ein Kontext-Objekt von deinem Framework abfragen, auf dem sie irgendwelche Dinge anstellen? Sie müssten dafür nur dein Hilfsmodul importieren und dann `get_context()` aufrufen.

Auf diesem Objekt könnten dann so eine Art Session für jedes Skript gestartet werden mit eigenem Namensraum, der nur für die Dauer der Session besteht. Am Ende des Skriptes werden die Modifizierungen mittels `commit()` an dein Framework übergeben und dieses "überträgt" es in TKinter-Aufrufe. Irgendwie sowas.

Ein unkontrollierbares `eval()` halte ich jedenfalls für sehr gefährlich und `ast.literal_eval()` ist vermutlich zu restriktiv für dein Vorhaben.

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 22:30
von Alfons Mittelmeyer
@snafu Einen Namensraum während einer Session gibt es nicht. Es ist einfach ein main() Aufruf und das war es dann. In Bruchteilen von Sekunden steht dann die GUI und existieren tut dann im Namensraum nur mehr eine nicht mehr benötigte Funktion main.

Die GUI existiert schon. Sie besteht aus Widgets und namenlosen Callbacks.

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Dienstag 25. August 2015, 22:51
von Alfons Mittelmeyer
DasIch hat geschrieben:Kann es sein dass du ein Pluginsystem suchst?
Weiß nicht, ich habe ja was ich brauche. War nur noch die Frage, wie ich unbenötigte Definitionen wegbekomme. Eine Funktion die immer main heißt, ist da wohl die Lösung, und die dann alles übrige lokal macht. Und ob imp.reload auch gut funktioniert anstatt compile und eval, kann ich ja noch testen.

Re: Was ist besser clean_eval() oder modifiziertes read()?

Verfasst: Mittwoch 26. August 2015, 06:20
von jens
Wir alle rätseln mal wieder, weil du es nicht schaffte dein eigentliches Problem zu schildern :?

Offensichtlich erzeugt du ein Python Modul welches eine tkinter gui ist, generisch. Die soll dann getestet werden können?!?

Also was spricht gegen subprocess?

Merk dir einfach, das eval und exec zu 95% der falsche Ansatz ist. Aber das sagte man dir ja auch schon des öfteren.