Gui Designer auf GitHub

Fragen zu Tkinter.
BlackJack

@Alfons Mittelmeyer: Nur wenn das Kreuzchen bei der Option das Leerzeichen statt Tabulator-Zeichen eingefügt werden sollen nicht gesetzt ist.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack Danke, jetzt habe ich gesehen, dass es da auch "Indent Type" gibt und nicht nur "Indent Width".
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Sirius3 In einer früheren Diskussion wurde geschrieben, dass das DynTkInter Format niemand haben will. Von JSON war die Rede und von XML. Wie stellt man sich das dann vor?

Code: Alles auswählen

# statt DynTkInter:
Button('Layout',text="""ON""",bg='green').grid(column='3',sticky='ew',row='0')

#evtl. JSON so oder doch lieber XML?
{"Layout": {"layout": {"type": "grid", "parameters": {"column": "3", "sticky": "ew", "row": "0"}}, "tkclass": "Button", "config": {"text": "ON", "bg": "green"}}}
Als Zwischenschritt könnte ich ja schon mal die Save Routine ändern und vereinfachen, denn das geht ja auch:

Code: Alles auswählen

Button('Layout',{"text": "ON", "bg": "green"}).grid({"column": "3", "sticky": "ew", "row": "0"})
Und statt die Syntax selber zu machen, brauche ich da nur JSON zu nehmen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sirius3 hat geschrieben:Ein "except: pass" macht Dir Fehlersuche unmöglich.
Da hast Du ja tolle Regeln im Kopf. Wenn der Benutzer als Farbe "grün" statt "green" eingibt, soll ich dann wirklich mywidget['bg']='grün' ohne except machen? Ja, wenn das System dann abstürzt, dann merkt er, daß er das falsch eingegeben hat. Aber freuen wird es ihn sicherlich nicht, wenn dann vielleicht eine Stunde Arbeit umsonst war.

Und unmöglich ist da die Fehlersuche nicht. Wenn man nämlich nach kurzer Animation das Eingabefeld wieder mit mywidget['bg'] füllt, merkt der Benutzer auch, dass das System das nicht angenommen hat. Außerdem sieht er auch, dass das Widget nicht grün geworden ist.
Programmabsturz als Empfehlung? Nein Danke.

Wahrscheinlich hast Du aber gemeint, man soll eine Fehlerbehandlung einbauen, wie etwa mit print den Fehler ausgeben.
Aber unmöglich ist es nicht, den Fehler zu erkennen, denn Gegenlesen geht auch.
BlackJack

@Alfons Mittelmeyer: Wenn eine Ausnahme eintritt und man die behandelt dann sollte man sie auch wirklich behandeln und nicht einfach nur ignorieren. Ausserdem ging es um die Fehlersuche in Deinem Programm, also Fehler die Du vielleicht gemacht hast und nicht um Fehleingaben vom Benutzer. Du hast zum Beispiel mindestens einen `NameError` in dem Code weil Du den Namen eines Arguments innerhalb einer Methode anders geschrieben hast als in der ``def``-Zeile. Wenn Du diese Methode innerhalb eines solchen ``try``/``except``-Blocks verwendest, dann wird die Fehlersuche schwieriger als sie sein müsste.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack Du hast natürlich recht damit, dass ich meine 'except: pass' Methoden überprüfen sollte und ob ich sie nur für Benutzereingaben benütze. In meinem Hauptmodul DynTkInter habe ich folgende 3 Methoden mit 'except: pass' :

Code: Alles auswählen

    # used by the GUI Creator: it tries to take the name of the widget as text. So Labels, Buttons and LabelFrames may be easily identified when doing the layout
    def text(self,mytext):
        try: self.config(text=mytext)
        except: pass

    # layout settings with the options as a string - is used by the GUI Creator
    def setlayout(self,name,value):
        dictionary = {}
        dictionary[name]=value
        try: self.layout(**dictionary)
        except: pass

    def setconfig(self,name,value):
        confdict={}
        confdict[name] = value
        try: self.config(**confdict)
        except: pass
Alle drei Methoden sind so richtig.

- text: Bei Widgets, welche die config Option 'text' haben, soll beim Anlegen der Widget Name als Text angezeigt werden - etwa bei Message, Label, Button, LabelFrame. Bei anderen Widgets soll das natürlich nicht abstürzen.

- setlayout: für Eingaben des Benutzers, nämlich für pack, grid oder place. Wenn er statt einer Spaltenangabe bei grid "wrdlbrmpfd" schreibt, soll das Programm nicht abstürzen. Kann sein, dass ich diese Funktion selber in meinem Programm benütze, statt pack, grid oder place. Ursprünglich hatte diese Methode kein try. Das hatte ich dann geändert für Benutzereingaben. Muss eben hier mal einen Fehler einbauen, um zu sehen, ob ich sie sonst noch benutze oder nicht.

- setconfig: für Eingaben des Benutzers bei Config Optionen. Dafür gilt dasselbe wie für setlayout. Muss auch hier mal schauen, ob ich das sonst noch benutze, etwa widget.setconfig('bg','yellow') anstatt widget['bg'] = 'yellow' oder auch widget.config(bg = 'yellow').

Jedenfalls haben diese Methoden sichtbare Effekte, bei denen man gleich sieht, geht es oder nicht. Und dass etwas nicht geht, hatte ich nicht gesehen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Alfons Mittelmeyer hat geschrieben:Alle drei Methoden sind so richtig.
Ein nacktes ``try... except`` ist eigentlich nie sinnvoll :!:

Deine Beispiele zeigen nichts, was das rechtfertigt!
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 Ich habe genau beschrieben, wofür das da ist. Und gestern hatte ich geschrieben, dass der Benutzer bei Methode 2 und 3 eine Fehlermeldung durch Rücklesen des Wertes bekommt. Es findet also eine Fehlerbehandlung statt. Und bei Methode eins erübrigt sich jegliche Fehlerbehandlöung. Man sollte nicht nur Regeln im Kopf haben, sondern auch den Sinn von etwas verstehen können.

Und Hyperion, wenn Du Dir ein offenes Denken erwerben willst, dann vergiss absolute Begriffe. Statt 'nie' benütze 'nicht oft' statt 'nichts' benütze 'wenig' oder 'nicht viel'. Dann übersetzen wir mal Deinen Einwurf:
Ein blankes ``try... except`` ist eigentlich nicht oft sinnvoll :!:

Deine Beispiele zeigen mir nicht viel, was das rechtfertigt!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Alfons Mittelmeyer hat geschrieben:@Hyperion Ich habe genau beschrieben, wofür das da ist.
Nö! Du hast nur beschrieben, *was* Du damit erreichen willst. Du hast aber offenbar immer noch nicht verstanden, *wie* man das tatsächlich erreicht, *ohne* sich Wege zu verbauen, *ungeplante* Ausnahmen zu erkennen...
Alfons Mittelmeyer hat geschrieben: Man sollte nicht nur Regeln im Kopf haben, sondern auch den Sinn von etwas verstehen können.
Richtig. Und letzteres hast Du offensichtlich im Bereich Exception-Handling (noch) nicht! Hättest Du das, würdest Du diese Regel nämlich selber verinnerlicht und damit richtig angewendet haben :twisted:

Um es Dir aber noch mal explizit zu machen: Man sollte immer nur die Ausnahmen abfangen, mit denen man zur Design-Zeit rechnet und die man sinnvoller Weise behandeln kann. Behandeln kann durchaus auch "ignorieren" sein, keine Frage. Aber Exceptions, von denen man *niemals* denken würde, dass sie auftauchen, sollte man nicht "verschlucken", wie Du es tust. Tritt so etwas nämlich auf, so wird sich Dein Programm im schlimmsten Fall total sonderbar verhalten oder auch an Stellen abstürzen, bei denen Du keine Ahnung hast, was da schief gelaufen ist (eben weil das schon viel weiter vorher passiert ist, Du es aber nicht mitbekommst).

Aber was rede ich mir den Mund fusselig... Du wirst es ja eh nicht durchdenken, recherhciere oder gar ausprobieren ;-)
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 hat geschrieben:Aber Exceptions, von denen man *niemals* denken würde, dass sie auftauchen, sollte man nicht "verschlucken", wie Du es tust.
Das siehst Du hier ganz falsch, denn es geht hier nicht um Exceptions, von denen ich *niemals* denke, dass sie auftauchen, sondern von denen ich denke, dass sie fortwährend auftauchen, und dass das das ganz normale Verhalten ist. Daher auch keine Fehlerbehandlng.

Und noch nichts gehört von EAFP Code? Also:

Code: Alles auswählen

# statt LYBL
if entry in myDictionary: del myDictionary[entry]

# EAFP
try: del myDictionary[entry]
except: pass
Quelle: https://www.jeffknupp.com/blog/2013/02/ ... xceptions/

Man sollte dabei natürlich noch abfangen, ob es myDictionary gibt.

Und ich könnte ja abfangen, ob es in tkinter 'config' gibt, das könnte ja auch umbenannt worden sein bei einer neueren tkinter Version. Aber dann würde sowieso nichts mehr gehen, und das merkt man dann schon
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Natuerlich geht es um die Exceptions mit denen du *nicht* rechnest, schliesslich ignorierst du sie einfach.

Wuerde dein Code tatsaechlich das tun was du behauptest wuerde er so aussehen:

Code: Alles auswählen

try:
    del myDictionary[entry]
except (KeyError, ExpectedException):
    pass
Und wenn `myDictionary` nun ein Objekt ist dessen `__getitem__` unerwartete Exceptions wirft, wirst du es nun merken, ganz anders als bei deinem bisherigen Code.

Lustig ist natuerlich auch, dass du hier Quellen anfuehrst, die aber gar nicht deine blanken `except` rechtfertigen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@cofi Ja kann man so machen. Und welcher Error wäre dann das, wenn es in tkinter nicht 'config' geben würde und auch nicht die Parameter? Die Werte der Parameter sollen aber beliebig sein, auch wenn sie falsch sind in Fall 2 und 3. in Fall 1 dagegen braucht es auch den Key nicht zu geben. Also das mit dem dictionary habe ich nicht gemacht. Da habe ich LYBL verwendet.

Ach so, ich kann ja auch ausprobieren, welche Fehler ich bekomme, indem ich etwa comfig schreibe und danach einen falschen Key verwende und danach einen falschen Wert nehme.
Natürlich kann in Fall zwei und drei ein falscher Key nicht passieren, denn was man mit config bekommt, sollte auch wieder mit config gehen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@cofi Das mit dem except bringt nicht viel, denn es gibt da nur eine Art von Fehler: tkinter.TclError

Und wenn ich bei tkinter Operationen schreibe: except tkinter.TclError: pass
dann kann ich mir das mit except tkinter.TclError auch gleich sparen und gleich pass schreiben. Aber OK schreibe ich das eben rein, auch wenn es überhaupt nichts bringt.
BlackJack

@Alfons Mittelmeyer: Das stimmt doch gar nicht, es gibt noch viele andere Ausnahmen. Das Du die nicht erwartest, heisst ja nicht das sie nicht auftreten können, und genau das ist ja das Problem: Wenn dann mal eine andere Ausnahme kommt, bekommst Du das nicht mit und das Programm verhält sich nicht so wie Du erwartest, aber Du weisst nicht warum und es ist schwerer *das* dann heraus zu finden als wenn man die Ausnahme zusammen mit einem Traceback bekommt.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack Es geht um diese 3 Methoden, bei denen das 'except: pass' so bemängelt wurde. Weisst Du was sich da ändert, wenn ich except tkinter.TclError mache? Überhaupt nichts. Das würde genau dann einen NameError ausspucken, wenn eine dieser vier tkinter Methoden nicht mehr existiert:

- config
- grid
- pack
- place

Aber soweit kommt es gar nicht, denn config, grid und pack, benutzt der GUI Designer bereits beim Hochfahren ohne try,except. Und place würde wahrscheinlich bereits bei place_info aussteigen, oder wenn der Benutzer ein neues Place Layout macht oder die Koordinaten im Basis Layout verändert. Nur in dem unwahrscheinlichen Fall, dass er eine bereits bestehende GUI bearbeitet und dabei nur über die Layout Optionen geht, wäre der Fehler unterdrückt worden, wenn es place nicht mehr gibt. Aber gesehen hätte er bestimmt, dass sich dabei nichts ändert.

Aber ich denke, dass da ein ungeheurer Aufschrei bei allen tkinter Nutzern wäre, wenn es place nicht mehr gibt. Gemerkt hätte man das ganz bestimmt!

FALSCH: ein bereits exisierendes Placelayout wäre gar nicht erst hochgefahren, wenn es place nicht mehr gibt. Also der Fehler wäre ohne Exception sowieso bereits vorher aufgetreten.

Und es geht hier auch nicht um Fehler im Programm, sondern um Fehler bei tkinter. Wenn mir etwa grid_info einen Key liefert, den dann grid(..) nicht nehmen will, das wäre ein Fehler, den ich leider nicht abfangen kann. Das läßt sich nur durch Testen herausfinden. Oder ändert sich etwas, wenn ich sashrelief von 'flat' auf 'raised' umstelle? Und siehe da, es macht es. Und da habe ich nichts hartkodiert. Hartkodiert ist nur die Sortierreihenfolge. Und wenn ich mich da vertippt habe oder einen Key nicht berücksichtigt habe, dann wird ein Key - etwa aus grid_info() oder aus config() - nicht da einsortiert, wo ich ihn haben wollte, sondern kommt erst ziemlich weit hinten.
BlackJack

@Alfons Mittelmeyer: Natürlich ändert sich was wenn Du explizit nur `tkinter.TclError` behandelst. Du siehst dann alle anderen Ausnahmen mit denen Du nicht rechnest mit Traceback. Das Du damit nicht rechnest heisst ja nicht das es sie nicht gibt. Wenn man sich mal nur die Methoden ansieht kann da *jede* Ausnahme kommen die es unter der Sonne gibt, nicht nur der `AttributeError` (nicht `NameError`) falls jemand eine der Methoden entfernt hätte.

Alleine ein `MemoryError` ist eine Ausnahme die man in der Regel gar nicht sinnvoll behandeln kann, schon gar nicht durch ignorieren, weil das Problem ja nicht weggehen wird.

Jede beliebige Ausnahme kann deswegen auftreten weil dort Objekte an Tk übergeben werden und die für Tk in Zeichenketten umgewandelt werden (müssen). Und dabei kann je nach Objekt alles mögliche an Ausnahmen auftreten.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@BlackJack und andere: *seufz* Als wenn man gegen eine Wand redete...

@Alfons: IdR. vermeide ich auch "immer" und "nie", denn in der Tat geht es meist eher um Prinzipien und nicht um absolut gültige Reglen (<Sexismus Modus> Wer eine Freundin hat, weiß wovon ich rede, denn die Worte "immer" und "nie" sind bei Streitereien mit dem weibichen Geschlecht offenbar sehr beliebt und fallen "immer" :mrgreen: </Sexismus Modus>)

Aber: Ich schrieb "eigentlich" - das ist imho Einschränkung genug an der Stelle. Wer in eine Situation kommt, in der man eine Ausnahme davon machen kann, der ist so gut, dass er weiß, was er tut. Das ist bei Dir übrigens noch nicht der Fall, denn bei Dir liegt eine andere Situation vor und Du zeigst fortwährend, dass Du den Sinn von Exceptions immer noch nicht verstanden hast!

Mich stört an Dir Thread übergreifend folgendes: Du "entdeckst" ein Dir total sinnvoll erscheinendes Muster und wendest es dann auf Teufel komm raus an. Wenn man Dir dann Schwächen oder Fehler daran nennt, stellst Du Dich zunächst überhaupt nicht in Frage und vertraust darauf, dass viele Regulars hier deutlich mehr Wissen und Erfahrung bezüglich Python haben als Du, und Dir folgerichtig *richtige und gute* Tipps geben, sondern Du verteidigst Deine Idee auf Teufel komm raus und suchst Quellen, die (vermeindlich) belegen, was Du behauptest. Denkst Du wirklich, dass Du Dich damit sinnvoll verbessern wirst?

Auch ein Albert Einstein hat die Grundlagen der Physik durch das Wissen von anderen gelernt, wie alle Schüler dieser Welt. Erst später hat er neue Ideen formuliert, die bis dato keiner hatte. Hingegen sind Leute, die das Rad komplett neu erfinden und sogar verbessern aufgrund von Isolation oder dem nicht vorhandenen Zugang zu Bildung, *extrem* selten. Zudem gehörst Du ja nicht zu letzteren, wie Deine aktive Teilnahme in diesem Forum beweist. Bleibt also nur der erste Fall...

Als intelligenter Mensch sollte man folgerichtig leicht zur Einsicht gelangen, dass man leichter und sicherer vorankommt, wenn man auf Ratschläge von anderen zurückgreift! Dabei muss man auch nicht alles als Gott gegeben hinstellen; kritisch hinterfragen sollte man Dinge durchaus. Aber dazu gehört es zunächst, diese Dinge genau zu durchleuchten und deren Intention zu verstehen. Mindestens diesen letzten Schritt machst Du sehr selten, wenn überhaupt einmal!

Und das nervt so gewaltig!

Natürlich könnte man das auch ignorieren, aber leider lesen hier ja auch nicht registrierte Menschen mit bzw. könnte falsche Aussagen finden und sich diesen Mist selber aneignen. Und das muss man eben verhindern, was leider nur durch eine aktive Teilnahme zu erreichen ist. Wäre das nicht der Fall, wären solche Threads von Dir wesentlich kürzer und eher Monologe - denn wer mag es schon wirklich, sture und beratungsresistente Menschen zu überzeugen? Ich glaube davon gibt es nicht allzu viele Regulars hier...
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 hat geschrieben:Das ist bei Dir übrigens noch nicht der Fall, denn bei Dir liegt eine andere Situation vor und Du zeigst fortwährend, dass Du den Sinn von Exceptions immer noch nicht verstanden hast!
Natürlich hat alles seinen Sinn. Python Programmmierer sind gewohnt, dass Python ihnen Fehler anzeigt und die wollen dass die auch immer angezeigt werden. C Programmierer sind gewohnt, dass sie eine Exception nur bekommen, wenn sie durch 0 teilen oder in einen geschützten Speicherbereich schreiben oder den Speicher zum Überlauf gebracht haben. Assembler Programmierer sind gewohnt, dass sie leicht einen Systemabsturz bekommen, wenn sie etwa statt in den Kodebereich in Daten springen, die der Prozessor natürlich nicht richtig als Programm ausführen kann.

Und ich bin gewohnt, Programme fast immer fehlerfrei so zu schreiben, dass sie funktionieren. Allerdings hat mein GUI Designer, da ein paar Stellen noch nicht ganz fertig sind, noch Fehler. Habe etwa die Laderoutine geändert, die nun eine main-Funktion erwartet und die save-Routine noch nicht nachgezogen. Also ein paar Baustellen, sind da noch. Und Überarbeitung ist noch nötig.

Es gibt auch Programmierer die soweit gehen:

Code: Alles auswählen

a = 5
if a != 5:
    print("Error: a = ",a," instead of 5")
Es gibt also auch übertriebene Fehlerbehandlung. Wo ist da der Mittelweg? Ich sehe natürlich ein, dass solche Exceptions und die empfohlene Behandlung schon sinnvoll sind, und an den besagten Stellen könnten natürlich schon Fehler auftreten, wenn etwa statt einem Widget eine Referenz auf etwas anderes übergeben wird. Und viele programmieren sehr unsauber, dass so etwas des Öfteren passiert. Also mache ich es eben auch so, zufrieden?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Alfons Mittelmeyer hat geschrieben:Und ich bin gewohnt, Programme fast immer fehlerfrei so zu schreiben, dass sie funktionieren.
Das ist ja direkt Comedygold. Die Art und Weise wie du da Exceptions handhabst ist gerade ein Beispiel, dass du fehlerhafte Programme schreibst.

Wenn du nur eine bestimme Art von Exception erwartest und/oder behandeln kannst, dann behandelst du nur diese bestimmte Art. *Alles andere* ist fehlerhafter und unsauber programmierter Code.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

cofi hat geschrieben:
Alfons Mittelmeyer hat geschrieben:Und ich bin gewohnt, Programme fast immer fehlerfrei so zu schreiben, dass sie funktionieren.
Das ist ja direkt Comedygold. Die Art und Weise wie du da Exceptions handhabst ist gerade ein Beispiel, dass du fehlerhafte Programme schreibst.
Nein das ist kein Beispiel für fehlerhaft. Das ist ein Beispiel, dass ich ganz gut auf jede Art von Fehlermeldung verzichten kann. Oder meinst Du ich hätte irgendeine Fehlermeldung bekommen, als ich mal ein Arztpraxisverwaltungsprogramm in Assembler geschrieben hatte?

Das heißt auf alle Fehlermeldungen kann man natürlich nicht verzichten. Syntaxfehler muss ein Compiler oder Assembler melden. Und das erwarte ich auch von Python.
Antworten