NameError: global name 'messagebox' is not defined

Fragen zu Tkinter.
Antworten
r0bnet
User
Beiträge: 10
Registriert: Montag 11. Januar 2010, 20:20

Hoi!

Hab ein Tool in Python 3 geschrieben, bei dem ich auf die Messagebox von tkinter zugreife.

Code: Alles auswählen

from tkinter import *
und dann rufe ich

Code: Alles auswählen

messagebox.showinfo('Datei auswählen!', 'Wählen sie eine Datei aus!')
In IDLE funktioniert alles und es erscheint eine Messagebox. Wenn ich auf das Script einen Doppelklick mache oder es aus der Konsole starte, dann bekomme ich immer den o.g. Fehler.

Woran liegt das?

Ich hab auch schon folgendes versucht:

Code: Alles auswählen

from tkinter.messagebox import showinfo
Leider ohne Erfolg.

greez
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

1.) Wir haben ein Tkinter Subforum ;-)

2.) Welches Script? Du zeigst nur einzelne Zeilen...

3.) Die Meldung ist doch eindeutig: Python kann mit "messagebox" nichts anfangen. Leider zeigst Du Dein Script ja nicht, weswegen ich mal vermute, dass Du dort das Modul tkinter nicht einbindest.

4.) *-Importe sind eigentlich unschön.
dahaze
User
Beiträge: 75
Registriert: Freitag 13. März 2009, 10:57
Wohnort: im Schwabenland

Hallo!

Ich schließ mich meinem Vorposter an^^! Ein kleines Beispiel bei dem der genannte Effekt auftritt wäre ganz praktisch.

Um auch ohne ein Beispiel ein Bisschen zu mutmaßen:
Hast du vielleicht parallel zu Python v3 eine Python v2.6 o.Ä. installiert, die vielleicht beim Starten des Scripts aus der Konsole gerufen wird?
Da heisst die Messagebox nämlich noch "tkMessageBox"....
Was dann allerdings normal bei "import tkinter" schon eine Exception werfen würde^^ :roll:
BlackJack

@r0bnet: Was heist "ohne Erfolg"? ``from tkinter.messagebox import showinfo`` funktioniert bei mir. Was ist die Fehlermeldung bei Dir?

@Hyperion und dahaze: Bitte den Beissreflex ausschalten, die einzelnen Zeilen sind genug -- kein Skript nötig. Es geht darum dass die einzelnen Zeilen in IDLE und in der Konsole unterschiedliches Verhalten zeigen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BlackJack hat geschrieben: @Hyperion und dahaze: Bitte den Beissreflex ausschalten, die einzelnen Zeilen sind genug -- kein Skript nötig. Es geht darum dass die einzelnen Zeilen in IDLE und in der Konsole unterschiedliches Verhalten zeigen.
Ich hatte Konsole als OS-Shell interpretiert, nicht als Python-Konsole! Evtl. ist das mein Fehler - evtl. auch Deiner. Da zuvor etwas von "Doppelklick" erwähnt wurde, habe ich geschlussfolgert, dass es ein mehrzeiliges Script gibt, bei dem vermutlich etwas am import nicht stimmt.
r0bnet
User
Beiträge: 10
Registriert: Montag 11. Januar 2010, 20:20

Sry, ich hatte auch gemerkt, dass es das falsche Forum ist, aber erst als es zu spät war ;)

Ich meinte auch die OS-Console.

Das Skript ist völlig irrelevant, da es nur um die besagte Funktion geht. Wenn ich das Skript aus IDLE starte, dann funktioniert alles und es kommt kein Fehler. Wenn ich es aus der Console starte ODER per Doppelklick, dann kommt der o.g. Fehler an der Stelle, wo ich die MessageBox aufrufe. Das Importieren der showinfo Funktion macht auch keine Probleme, nur dass nach wie vor der Fehler erscheint.

Ich hab nun anstatt

Code: Alles auswählen

from tkinter import *

Code: Alles auswählen

import tkinter as tk
from tkinter.messagebox import showinfo
from tkinter.filedialog import askopenfilename
genommen. Nun funktioniert es über die OS Shell. Finde ich sehr seltsam, da es in IDLE auch ohne die beiden unteren Zeilen funktionierte.

Die filedialog Zeile war auch nötig, da ich den Filedialog auch benötige. Als ich die Zeile noch nicht drin hatte kam diese Meldung:

Code: Alles auswählen

AttributeError: 'module' object has no attribute 'filedialog'
bei der folgenden Zeile:

Code: Alles auswählen

self.__regfile = tk.filedialog.askopenfilename()
Weiß jemand, warum da nicht import tkinter as tk ausreicht?

greez
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

r0bnet hat geschrieben:Das Skript ist völlig irrelevant, da es nur um die besagte Funktion geht.
Mir ging es ja grad um die exakten Aufrufe: Also exakt welcher import und dann exakt welcher Aufruf. Ich hatte eben vermutet, dass Du das import evtl. eben weggelassen hattest.

Generell solltest Du Dir mal im Tutorial durchlesen, wie "import" funktioniert; speziell für Dich interessant ist der Absatz über Packages
http://docs.python.org/py3k/tutorial/mo ... l#packages

Ich denke nach der Lektüre (6.4.1!) sollte es Dir klar sein, was es mit den *-importen hier auf sich hat :-)
r0bnet
User
Beiträge: 10
Registriert: Montag 11. Januar 2010, 20:20

Da stand nun nichts drin, was mir wirklich neu ist.

Kann mir jemand die Frage beantworten, warum ich keinen Fehler bekomme, wenn ich folgendes in IDLE teste:

Code: Alles auswählen

import tkinter as tk

tk.filedialog.askopenfilename()
Aber es kommt ein Fehler, wenn ich es über die OS Shell aufrufe?
Fehler:
Traceback (most recent call last):
File "C:\ProLeiS3_Release\trunk\ocx\test.py", line 3, in <module>
tk.filedialog.askopenfilename()
AttributeError: 'module' object has no attribute 'filedialog'
Verstehe ich nicht so ganz. Nur wenn ich noch explizit

Code: Alles auswählen

from tkinter.filedialog import askopenfilename
angebe, dann klappt es.

greez
BlackJack

@r0bnet: IDLE ist selbst in `tkinter` programmiert und wenn Dein Code im gleichen Interpreter läuft wie IDLE dann sind diese Module schon importiert, da sie von IDLE verwendet werden.
r0bnet
User
Beiträge: 10
Registriert: Montag 11. Januar 2010, 20:20

Okay, daran hat es wohl gelegen. :)

Danke an euch!

greez
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

BlackJack hat geschrieben:@r0bnet: IDLE ist selbst in `tkinter` programmiert und wenn Dein Code im gleichen Interpreter läuft wie IDLE dann sind diese Module schon importiert, da sie von IDLE verwendet werden.
Ganz so ist es nicht. Es liegt vielmehr daran, dass IDLE (auch die eingebaute IDLE-Shell) beim Import von tkinter offensichtlich ungefragt zusätzliche Module importiert, nämlich die Module "tkinter.modulname".

IDLE-Shell (Python 3.1):

Code: Alles auswählen

>>> type(tkinter.filedialog)
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    type(tkinter.filedialog)
NameError: name 'tkinter' is not defined
>>> import tkinter
>>> type(tkinter.filedialog)
<class 'module'>
"Normale" Python-Shell:

Code: Alles auswählen

>>> import tkinter
>>> type(tkinter.filedialog) 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'filedialog'
>>> import tkinter.filedialog
>>> type(tkinter.filedialog) 
<class 'module'>
r0bnet
User
Beiträge: 10
Registriert: Montag 11. Januar 2010, 20:20

Ha, also war es doch nicht mein Fehler und da läuft was nicht so, wie es soll.

Ich hab nun alles so hinbekommen, wie es soll, aber irgendwas hatte mich daran halt gestört.

Kennt nun wer den genauen Grund für das Verhalten von IDLE mit tkinter?
BlackJack

@numerix: Das passiert nicht erst wenn man `tkinter` importiert denn `tkinter` *ist* zu diesem Zeitpunkt ja schon importiert, genau wie die anderen Module in dem Paket. Aus einem frisch gestarteten IDLE:

Code: Alles auswählen

>>> import sys
>>> sys.modules['tkinter']
<module 'tkinter' from '/usr/lib/python3.1/tkinter/__init__.py'>
>>> sys.modules['tkinter'].filedialog
<module 'tkinter.filedialog' from '/usr/lib/python3.1/tkinter/filedialog.py'>
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

BlackJack hat geschrieben:@numerix: Das passiert nicht erst wenn man `tkinter` importiert denn `tkinter` *ist* zu diesem Zeitpunkt ja schon importiert, genau wie die anderen Module in dem Paket.
Ja, verstanden. Meine Überlegung war:
Wenn IDLE tatsächlich schon beim Start tkinter importiert, dann müsste ja auf tkinter-Attribute zugegriffen werden können, ohne tkinter explizit importieren zu müssen. Das funktioniert aber nicht. Siehe mein Beispiel. Das war natürlich zu kurz gedacht und nicht richtig hingeguckt, denn es kommt ja ein "NameError", weil der Bezeichner tkinter im lokalen Namensraum nicht vorhanden ist.

@r0bnet: Das war schon vorher klar, nicht erst seit meinem (unzutreffenden) Beitrag.
Antworten