Alfons Mittelmeyer's Wundersame Welt

Fragen zu Tkinter.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da ist nichts lausig definiert. Das vom Interpreter ausgefuehrte Skript wird *implizit* in ein Modul gesteckt, mit dem Namen '__main__'.

Kannst ja mal ueber diesen Ausdruck meditieren:

Code: Alles auswählen

python -c "import sys; import pprint; pprint.pprint(sys.modules); pprint.pprint(dir(sys.modules['__main__']))"
So. Jetzt hab' ich dem Troll auch mal Futter gegeben :twisted:
Sirius3
User
Beiträge: 17745
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: also jetzt hör auf mit dem Quark. Vor zwei Beiträgen schreibst Du noch, dass Module und Skripte was völlig verschiedenes sind und jetzt behauptest Du plötzlich, dass alles ein Modul sei? Du drehst alles so, wie es Dir gefällt, stellst alle anderen als Idioten hin und glaubst, keiner würde Dich durchschauen?

Du schreibst kein Python und willst das auch gar nicht, wenn Du Zeile für Zeile interpretierst, wie es Dir passt, statt das zu nehmen, was Dir Python von Haus aus bietet. Hier gibt es viele, die wollen Python lernen, und nicht Deine neue Sprache, die nicht einmal einen Namen hat. Wenn also jemand Alfonsisch lernen will, dann solltest Du ein Forum aufmachen, und die Leute dort beglücken.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Sirius3 Ich habe überhaupt nichts umgeschwenkt, ich hatte lediglech Hyperion gefragt, warum wir überhaupt streiten, webnn er meint,l dass auch mit compile und exec ausgeführter Code 'importiert' wäre:

Code: Alles auswählen

Und in Deinem Post schreibst Du jetzt sogar, dass was ich tue, nämlich compile und exec auch importiert wäre. Ja wozu streiten wir uns dann überhaupt? Dann kann ja jeder zufrieden sein, denn ich habe es ja dann doch importiert, oder?
Und statt über etwas zu streiten, sollten wir uns bemühen, da einen Unterschied zu erkennen oder festzulegen, denn wer einen Unterschied erkennt, kann das ausnützen, um etwas zu implementieren. Wer keinen Unterschied erkennt oder erkennen will, kann einen solchen leider nicht für eine Implementierung benützen.
Wenn im Mainscript genau das steht und sonst nichts:

Code: Alles auswählen

def no_script():
    print("I'm a script")
Dann ist das kein Code für ein Script oder ein unfertiger Code für ein Script. Hier wird eine Funktion definiert, aber nicht aufgerufen. So etwas macht man bei Modulen. Man importiert sie um dort Funktionen aufzurufen.

In einem Script dagegen befinden sich viele Funktionsaufrufe und auch viele Zeilen beginnen auch ganz links ohne in Funktionen eingebunden zu sein. Das mag für ein Modul für die Initialisierungsphase ja auch durchaus zutreffen. Aber in einem Script verwendet das Script alle in ihm definierten Funktionen selber und keine Funktion darin ist dafür gedacht, von außerhalb aufgerufen zu werden und idealerweise soll ein Zugriff von außerhalb auch gar nicht möglich sein.

Reicht das so mal für das Erste als grober Unterschied?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Wozu streiten wir uns überhaupt? Nur weil das von meinem Programm erzeugte ASCII Datenformat eine rein zufällige starke Ähnlichkeit mit Python Code besitzt - ok nicht rein zufällig und auch nicht nur starke Ähnlichkeit - sondern 100% - ich hatte eben gedacht ich tue jemandem einem Gefalllen, wenn Python mit tkinter auch so aussieht wie Python mit tkinter - nur deshalb muss dieses ASCII Format unbedingt als Python Module mit 'import' implementiert werden?

Irgendwelche Daten in irgendwelcher Form sollten keinesfalls als Module importiert werden. Vielleicht sollte man da die Syntax ändern, damit man nicht auf solche dummen Ideen kommt - dumm wären die gar nicht - aber die Forderung dass es so sein müsse, die zeigt von Engstirnigkeit.

Wie wäre es etwa mit ';' nach jedem Statement. Und statt ':' und eingerückt geschweifte Klammern. Statt def sollte es function heißen. Class sollte man groß schreiben und statt 'import' besser 'include'.

Würde das reichen um von der Forderung nach 'import' Abstand zu nehmen? Oder wären weitere Modifikationen nötig - dass man in etwa in die Richtung php, javascript, C# oder auch squirrel geht?
Sirius3
User
Beiträge: 17745
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: wie oft denn noch. Es gibt keinen Unterschied zwischen einem Skript und einem Modul. Jede .py-Datei kann man importieren. Ob das sinnvoll ist oder nicht, entscheidet nur der Author. Wenn man Funktionalität braucht, die in einer anderen .py-Datei steht, dann wird diese importiert. Daher muss sie auch so geschrieben sein, dass sie sinnvoll importierbar ist. Du kannst natürlich auch nicht sinnvoll importierbare "Skripte" (Dein Wortlaut) schreiben, wo Du dann zusätzlich noch irgendwelche compile-Magie brauchst. Du kannst aber auch, wenn Du in den Nachbarort willst, einmal um die ganze Welt laufen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Sirius3 Ja genau darum geht es. Du hattest geschrieben:

Code: Alles auswählen

Wenn man Funktionalität braucht, die in einer anderen .py-Datei steht, dann wird diese importiert. Daher muss sie auch so geschrieben sein, dass sie sinnvoll importierbar ist.
Da bin ich ganz Deiner Meinung. Das schließt aber auch ein, dass man nicht importiert, was äußerst unsinnig ist, dass man es importiert.

Was ein Script ist und ein Modul mag jeder nennen oder will. Ich verstehe unter Modul ein mit import importiertes Modul. Dann schreibe ich eben in Zukunft statt Modul eben jedes Mal 'mit import oder dessen Derivaten (etwa imp.load' ) importiertes Modul'. Vielleicht wird es dann deutlicher. Vielleicht kann mir dann auch jemand schreiben, wie ich am Besten das Main Script nennen soll, das ja anscheinend auch ein Modul genannt wird aber ein nicht 'mit import oder dessen Derivaten (etwa imp.load' ) importiertes Modul' ist.

Ach nochmals zurück zum Mainscript. Das aufzurufen ist keine 'Magie'. Wenn es zu lang ist, kann man es auch in kleinere Teile teilen, die man dann vor Python3 mit 'filexec' ausführen konnte. Da diese Funktion aber unnötig ist, weil sie aus einem kurzen Ausdruck mit drei Komponenten gebildet werden kann, hat man in Python3 darauf verzichtet. Ebenso wenig wie die Ausführung des Main Scripts sollte man die Ausführung durch 'filexec' oder den in Python3 gebräuchlichen Ausdruck 'Magie' nennen. Also von 'compile' Magie zu sprechen, dafür gibt es keinen Grund, es sei dem, man würde Computer, Compiler, Programmiersprachen und dergleichen als großen Zauber ansehen.

Und 'filexec' kann man auch lokal innerhalb einer Funktion ausführen. Damit hat das, was ausgeführt wird, nur temporäre und lokale Gültigkeit innerhalb dieser Funktion und wandert nach Beendigung dieser Funktion in den Garbage Collector, zumindest, was davon nicht noch global irgendwie referenziert ist, etwa durch die nicht nur lokal bestehenden tkinter Widgets und eine Referenz in deren command oder deren 'bind' eines Events.

Und genauso gehört sich das auch. Dagegen ist das unbedingte global Importieren Wollen von lokalen Variablen durch 'import' eines Moduls, bevor die Funktion beendet wird und der Garbage Collector greift, eine der hirnverbranntesten Ideen, die mir untergekommen ist und mir unbegreiflich, wieso man das so will.

Sicher lassen sich gewissse Variableninhalte irgendwie vor Rücksprung aus einer Funktion auch in ein File schreiben, das man dann danach importieren kann. Man muss sich dann nur überlegen, wie man dabei mit referenzierten Objekten umgeht und wie man die dann adäquat herausschreiben kann. Bei den tkinter Widgets könnte ich durchaus helfen. Andere Objekte muss man sich selber überlegen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Alfons Mittelmeyer hat geschrieben:Das schließt aber auch ein, dass man nicht importiert, was äußerst unsinnig ist, dass man es importiert.
Richtig! Solche Sachen importiert man nicht und gut ist. Denn wenn es unsinnig ist, ein Modul zu importieren, dann nutzt man es natürlich auch nicht über andere finstere schwarze Magie, wie Du sie betreibst. Man nutzt es einfach gar nicht, überhaupt nicht. Deutlicher kann ich es nicht ausdrücken...

Module müssen genau wie Klassen, Funktionen und jedes andere Python Konstrukt sorgfältig gestaltet werden, denn nur dann kann uns will man diese auch benutzen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Hyperion Ruf einfach Python nicht auf. Denn danach wird - sofern angegeben - das Mainscript ausgeführt. Und wenn Du so etwas als 'finstere schwarze Magie' ansiehst, dann lass es einfach bleiben.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Stellst Du Dich absichtlich dumm? Natürlich gibt es immer und in jeder Sprache irgend einen Einstiegspunkt, der ggf. andersartig ist oder bestimmten besonderen Konventionen folgt. Das ist übrigens auch in C so, was Du doch so super beherrschst, wie ich mich dunkel erinnere...

Das ist aber von der Sprache so vorgesehen und stellt den idiomatischen Weg dar, das zu tun. In Python ist das eben der ``if __name__ == "__main__"`` Hook. Aber von diesem Punkt an, nutzt man dann ``import``, um Code aus anderen Modulen zu verwenden.

Das sind einfach Fakten und anerkannte Konventionen. Es würde Dir gut tun, Dich endlich einmal vernünftig damit zu befassen. Du könntest so viel bessere Software schreiben, wenn Du Dich nicht dermaßen unverständlicher Weise dem Erlernen von Python verweigern würdest... und Du würdest Dich hier nicht so sozial ins Abseits stellen!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Hyperion ja, das Main Script als Einstiegspunkt, das ist wohl 'gute und weiße Magie' aber 'filexec' das ist dann bei Dir 'finstere schwarze Magie'. Ja sind wir hier im Mittelalter? Und Du bist so etwas wie der Großinquisitor?
BlackJack

@Alfons Mittelmeyer: Das ist keine weisse Magie sondern der vorgesehene Weg während Dein Vorgehen ein Irrweg ist. Das sagt Dir nicht *ein* Grossinquisitor sondern mehrere erfahrene Python-Programmierer. Auf einem mittelalterlichen Kreuzzug scheinst eher Du Dich zu befinden.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack Ich zwinge keinen Menschen, irgend etwas zu benutzen, was er nicht will. Hier dagegen scheint man gerne andere zu irgendwelchem Blödsinn zwingen zu wollen, wie etwa, dass man statt filexec zu verwenden, importieren muss, Mein Grundsatz ist der Gleichbehandlungsgrundsatz, also dass wenn jemand etwas für eine Funktion a fordert dasselbe auch für eine Funktion b gelten muss. Und wenn bei 'fileexec' importiert werden muss, dann muss dasselbe auch für 'readline' gelten. Also beim Lesen von Zeilen aus einem ASCII File sollten da die Zeilen als Module implementiert werden. Da sollte man eben mal darüber nachdenken, ob man eine Special Edition 'Python for Trolls' herausgeben sollte.
BlackJack

@Alfons Mittelmeyer: Man muss importieren wenn importieren der offensichtliche Weg ist und das ist er nun mal auch wenn Du das nicht wahrhaben willst. Der ”Gleichbehandlungsgrundsatz” verfängt nicht, weil es wenn es mehrere Wege gibt „pythonisch“ ist zu fragen welches denn der offensichtliche ist, und dann nur den zu verwenden. Das ist nicht immer eindeutig welcher Weg offensichtlich ist, aber bei ``import`` versus `compile()` und `exec` ist es das.
Also beim Lesen von Zeilen aus einem ASCII File sollten da die Zeilen als Module implementiert werden.
Äh, was? Entweder bist Du auf Drogen oder Du hast mal wieder Begriffe verquer umdefiniert ohne jemandem was davon zu verraten.

Wir brauchen kein Python für Trolle, sondern weniger Trolle — also Dich nicht wirklich.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack Mir ist die Lösung für das Problem eingefallen. Statt diesen Ausdruck mit read,compile und exec zu verwenden, mache ich eine Funktion daraus. Diese Funktion kommt in eine Modul für Funktionen zum Anpassen und wem es dann nicht gefällt, dass fileexec auf compile und exec Basis arbeitet, kann dann seine Version auf import Basis hineinschreiben.

Die andere Möglichkeit ist aber auch, dass jemand die Optionen, wie splitten der GUI in kleinere Teile und Verlinkung mittels LinkButton sowie LinkLabel nicht benutzt. Damit hat man dann nur ein Script, das man in sein Main Script kopieren kann oder auch importieren kann.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack also im Prinzip würde das schon funktionieren:

Code: Alles auswählen

import imp

def file_exec(filename,globals=None,locals=None,module_counter = [0]):

    counter = module_counter[0]
    module_counter[0] += 1
    return imp.load_source('module_'+str(counter),filename)

file_exec("print_test.py")
file_exec("print_test.py")
file_exec("print_test.py")
Überlegen muss man sich aber noch, wie man dabei die Namespaces übergeben kann.

Also ungeklärte Frage: Wie kann man dabei den Namespace übergeben?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Und so etwas ist auch noch zu bedenken:

Bild

So etwas hat 77 Frames mit je zwei Labels drin und einem Icon. Hinzu kommen noch zwei Callbackfunktion und zwar dreimal je für den Frame und je für die zwei Labels. Ungeschickt implementiert, könnte das dann über 500 mal Scriptladen sein. Das Fenster 20 mal herbeigeklickt ergäbe dann Zehntausend Module.

Und so etwas will man hier unbedingt haben?
BlackJack

@Alfons Mittelmeyer: Ich verstehe das Problem nicht und was „500 mal Skriptladen“ überhaupt bedeuten soll. Das ist exotisch und ja, anscheinend ungeschickt implementiert. Wenn man das auf normalem Weg löst, dann ist das einfach ein wenig Code in einem Modul das einmal importiert wird und jedes mal wenn der Benutzer das Fenster ”herbeiklickt” wird der Code darin ausgeführt um das Fenster anzuzeigen. Das ist der offensichtliche Weg das zu lösen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Natürlich wäre 500 mal laden, nämlich für jeden Frame darin für jeden Label darin für jedes Icon usw sehr ungeschickt und bei mir ist das alles auch nur ein Script. Aber wenn man auch http:// links im Sinn hat, dann sollte man aus Erfahrung wissen, dass da bei manchen Seiten viel nachgeladen wird, und solche Fälle durchaus vorkommen könnten und zehntausend Module auch ganz schnell verbraten sein könnten und wofür? Nur für global definierten Garbage. Denn eine Seite verlassen bedeutet schlichtweg nur mehr Garbage.
BlackJack

@Alfons Mittelmeyer: Jetzt erfindest Du schon wieder Probleme die niemand hat. Zehntausend Module? Zeig mal!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack Natürlich hat man nicht schnell Zehntausend Module, die man benutzt aber ohne eine Modulgarbage Collector hat man die schnell, wenn man nämlich einfach für jeden Ladevorgang den Namenszähler für Module erhöht und alles jeweils immer wieder in ein neues Modul spielt.

Aber mir ist da schon eine Idee gekommen, nämlich ein Garbage Modul Collector. Immer wenn man entsprechende Widgets löscht wird dann auch das entsprechende Modul als Garbage markiert und zum neu Überschreiben freigegeben.

Damit könnte man das Problem lösen. Das mit dem Namespace geht auch. Man importiert nämlich nicht gleich, sondern schreibt zuerst einen Header mit dem Namespace, liest dann den Sript Inhalt dazu, schreibt das in eine temporäre Datei und die importiert man dann und löscht sie gleich wieder. Ist aufwändiger als gleich mit compile und exec aber durchaus machbar.
Antworten