messagebox py3.7.0 - py3.4

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
DB7WN
User
Beiträge: 49
Registriert: Samstag 18. März 2017, 22:11

Hallo allerseits!
ich habe ein Pythonscript in einem Netzlaufwerk, zu dem ich von zwei verschiedenen PCs zugreife. Auf einem PC ist Py3.7.0 installiert, auf dem anderen Py3.4
In mindestens zwei Fällen reagieren die beiden Pythons unterschiedlich und es tritt sogar ein Fehler auf.

Die Zeile: messagebox.showerror('Fehler', 'kein Dateiname')
ruft unter Py3.7.0 die Fehlermeldung "messagebox ist nicht definiert " hervor. In Py3.4 dagegen funktioniert das wie gewünscht.

Wie gesagt, ist das Script absolut dasselbe.

Ist da ein Kompatibilitätsproblem? Google konnte mir nichts dazu sagen.
Benutzeravatar
__blackjack__
User
Beiträge: 14033
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DB7WN: Wie hast Du `messagebox` denn definiert/importiert? Kann es sein, dass sich Dein Skript darauf verlässt das `messagebox` automatisch mit `tkinter` importiert wird? Das ist zumindest bei Python 3.6 nicht der Fall. Das riecht so wie es da steht auch nach einem Sternchen-Import.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
DB7WN
User
Beiträge: 49
Registriert: Samstag 18. März 2017, 22:11

Ich mache das so: from tkinter import *

Ja, ich hab mal irgendwo gelesen, dass es bei dem Import irgendwelche Probleme geben kann, habs aber nicht richtig kapiert.
Vielleicht bist du so nett und erklärst mir das nochmal.
Benutzeravatar
__blackjack__
User
Beiträge: 14033
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DB7WN: Ganz konkret hast Du hier das Problem das `messagebox` ein Modul im `tkinter`-Package ist und das auf diese Weise nicht garantiert ist, dass das importiert wird. Das musst Du schon *explizit* importieren. Und *-Importe sind Böse™, weil man sich da *alles* aus dem importierten Modul in das aktuelle Modul holt und man nicht mehr so leicht nachvollziehen kann was woher kommt und zudem die Gefahr von Namenskollisionen besteht.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
DB7WN
User
Beiträge: 49
Registriert: Samstag 18. März 2017, 22:11

Ich habs heute Nacht noch ausprobiert. Mit "from tkinter import messagebox" geht es.
Danke für den Tip.
Bei nahezu allen Scriptbeispielen, die ich über Google gefunden habe und auch in meinem kleinen Handbuch "Python Ge-packt" wird der Import mit Sternchen verwendet.
Benutzeravatar
__blackjack__
User
Beiträge: 14033
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DB7WN: Beliebige Scriptbeispiele über Google können beliebig schlecht bis falsch sein. Insbesondere seit Python durch den Raspi ähnliche Leute angelockt hat wie PHP und viele Leute die in anderen Sprachen programmieren können, aber Python nur sehr oberflächlich angeschaut haben, mal schnell was zusammen hacken. Und dann schreiben die alle voneinander ab und/oder kopieren einfach Quelltextfragmente. Teilweise ohne zu verstehen was sie da kopiert und verändert/integriert haben.

*-Importe sind praktisch in einer interaktiven Python-Shell oder bei Modulen die explizit vom Programmierer des Moduls für diesen Zweck vorgesehen sind. `pygame.locals` würde mir da spontan einfallen. Ansonsten ist das nicht ganz ungefährlich weil man sich ja nicht nur alles in dem Modul direkt definierte importiert was in der Dokumentation steht, sondern auch alles was das Modul importiert hat. Dann kann es genau zu solchen Situationen kommen die Du hast: Es kann sein, dass man implizit Namen importiert hat, welche gar nicht da sein dürften ohne das man sie explizit von woanders importiert. Und da das nicht Teil der öffentlichen, dokumentierten API ist, kann sich das auch von Version zu Version ändern. In Python 3.6 hast Du nach einem ``from tkinter import *`` auch die Module `enum`, `sys`, und `re` importiert und man könnte die einfach so verwenden. Das ist aber nicht garantiert.

So ein *-Import macht zudem einen guten Teil der Trennung von Namensräumen zunichte, also den Grund warum man überhaupt Module verwendet.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
DB7WN
User
Beiträge: 49
Registriert: Samstag 18. März 2017, 22:11

Ich versuche jetzt mal die Import-Methode zu ändern, also statt "from tkinter import *" "import tkinter as tk".
Dass jetzt das Erzeugen von fenster, widgets etwas anders funktioniert, habe ich bemerkt und im Prinzip geht das auch: Also statt "fenster = Tk()" jetzt "fenster = tk.TK()". Bei Widgets genauso. Was muss ich aber bei Listboxen machen?

#alt
from tkinter import *
fenster = Tk()
box = Listbox(fenster)
box.pack()
box.delete(0, END)
fenster.mainloop()
#Das hat funktioniert

#neu
import tkinter as tk
fenster = tk.Tk()
box = tk.Listbox(fenster)
box.pack()
box.delete(0, END)
fenster.mainloop()
#das funktioniert nicht mehr -> Fehler "NAME END is not defined"

Ich bin nicht zu faul zum suchen, aber ich finde nichts. Im Netz und auch in meinen beiden Büchern wird der "Sternchenimport" von tkinter praktiziert, wobei "box.delete(0, END)" auch funktioniert.
Benutzeravatar
kbr
User
Beiträge: 1507
Registriert: Mittwoch 15. Oktober 2008, 09:27

Beim Sternchen-Import war END da - und nun rate mal, woher es kam.
DB7WN
User
Beiträge: 49
Registriert: Samstag 18. März 2017, 22:11

verrat`s mir
Benutzeravatar
ThomasL
User
Beiträge: 1378
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

from tkinter import END
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Sirius3
User
Beiträge: 18267
Registriert: Sonntag 21. Oktober 2012, 17:20

Es muß eben genauso heißen wie bei Tk oder Listbox: tk.END
DB7WN
User
Beiträge: 49
Registriert: Samstag 18. März 2017, 22:11

Ich hab mir den Wolf gesucht im Netz und das gefunden: "from tkinter.constants import *".
Das importiert nicht nur END, sondern wohl auch andere Konstanten wie TOP, LEFT, RIGHT, usw.
Es ist immer schwierig, wenn man nicht weiß, was man suchen soll.
Sirius3
User
Beiträge: 18267
Registriert: Sonntag 21. Oktober 2012, 17:20

Du brauchst nicht lange Suchen, sondern nur das ausprobieren, was Du für die anderen Namen auch schon gemacht hast:

Code: Alles auswählen

>>> import tkinter as tk
>>> tk.END
'end'
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi DB7WN

Du kannst die Konstante auch als klein geschriebener String tk.END = 'end' verwenden:

Code: Alles auswählen

import tkinter as tk
fenster = tk.Tk()
box = tk.Listbox(fenster)
box.pack()
box.delete(0, 'end')
fenster.mainloop()
Best 73 de wuf :-)
Take it easy Mates!
DB7WN
User
Beiträge: 49
Registriert: Samstag 18. März 2017, 22:11

Danke allerseits, jetzt funktionierts. Dass man auch den String "end" benutzen kann, hatte ich nicht gefunden.
Ich fürchte, dass ich beim Nächstenmal wieder "auf den Schlauch stehe". Aber dafür haben wir ja das Forum. Ich weiß einfach nicht, was sich in tkinter noch alles verbirgt und was man extra aufrufen muss. Das ist ein grundlegendes Verständnisproblem bei mir.
Sirius3
User
Beiträge: 18267
Registriert: Sonntag 21. Oktober 2012, 17:20

@DB7WN: nein, Du solltest NICHT den String 'end' benutzen, dafür sind ja die Konstanten, tk.END, usw., da. Ich verstehe nicht, wo konkret Du damit noch Verständnisprobleme hast? Alles was sich im Modul tkinter befindet, läßt sich über tk.xy ansprechen.
Benutzeravatar
__blackjack__
User
Beiträge: 14033
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DB7WN: Um tkinter zu verstehen muss man letztlich auch Tk lernen. Das ist in Python nicht komplett dokumentiert, weil es ja nur eine Anbindung an eine an sich ganz gut dokumentierte Bibliothek ist. Wenn man Tk richtig verstehen will, muss man sich auch Tk/Tcl anschauen zumindest so weit anschauen das man den GUI-Teil versteht. Eine wichtige Grundlage von Tcl ist, das diese Programmiersprache so ziemlich alles über Zeichenketten löst. Das ist *der* Datentyp in Tcl.

Ich würde in Python dann aber doch lieber die Konstanten verwenden, statt auch da alles über manuell geschriebene Zeichenkettenliterale zu erledigen.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Antworten