from modulname import *

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
mcdaniels
User
Beiträge: 168
Registriert: Mittwoch 18. August 2010, 19:53

Hallo,
ich dachte eigentlich, dass ein:

Code: Alles auswählen

from tkinter import *
sämtliche Funktionen des tkinter-Modules ladet.

Nun habe ich in folgendem Test auf den "colorchooser" zurückgreifen wollen, der ja auch von tkinter "kommt":

Code: Alles auswählen

def mColor():
    mycolor = colorchooser.askcolor()
    mylabel4 = Label(mGui,text=mycolor).pack()
läuft das Ganze auf einen NameError hinaus.

Erst wenn ich:

Code: Alles auswählen

from tkinter import colorchooser
durchführe, läuft es.

Frage: Müsste nicht der "*" Import alles importieren?
BlackJack

@mcdaniels: Nicht wenn `colorchooser` ein Modul (oder Paket) ist, was zu dem Zeitpunkt wo Du den (bösen) Sternchenimport gemacht hast, noch gar nicht geladen war.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Nein. Was "from modulname import *" tut, kann das Modul modulname selber entscheiden, indem es __all__ setzt (eine Liste von Strings). Alle Namen, die in __all__ enthalten sind, werden dann bei einem *-Import importiert. Aber das kann dir alles völlig egal sein, weil *-Importe verpöhnt sind. Sternchenimporte sorgen für sogenannte "Namespace-Pollution", d.h. der Namensraum wird mit Namen und Objekten vollgemüllt, die du gar nicht benutzt. Außerdem weiß der Leser des Codes gar nicht, woher ein Name kommt, wenn du irgendwo im Code "bla(23, 42)" stehen hast, aber bla nirgendwo *explizit* importiert wird.
import this hat geschrieben:Namespaces are one honking great idea -- let's do more of those!
Benutzeravatar
bwbg
User
Beiträge: 407
Registriert: Mittwoch 23. Januar 2008, 13:35

Für tkinter hat sich

Code: Alles auswählen

import tkinter as tk
eingebürgert um sich nicht blutig tippen zu müssen.

Allgemein toleriert werden *-Importe im interaktiven Interpreter.

Darüber hinaus ist mir nur ein wirklich sinnvoller Einsatz für *-Importe untergekommen: OpenGL (man könnte ja mal sammeln, aber ich denke, dass da nicht viel zusammen kommen wird).

Grüße ... bwbg
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
BlackJack

@bwbg: PyQt/Pyside. Da haben alle Klassen ein Q am Anfang. Das ist auch halbwegs ungefährlich. Allerdings verwischt man so die Grenze zwischen den Modulen (`QtGui`, `QtCore`, und so weiter).
Benutzeravatar
bwbg
User
Beiträge: 407
Registriert: Mittwoch 23. Januar 2008, 13:35

Zumal ich aus meiner Amateursicht jetzt keine Namenskollisionen zwischen QtCore und QtGui, etc. erkennen kann.
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
mcdaniels
User
Beiträge: 168
Registriert: Mittwoch 18. August 2010, 19:53

Hallo, danke für eure Antworten. Ich stelle mal das "Konstrukt" hier rein. Geht rein um Testzwecke.

Hier haben wir das böse:

Code: Alles auswählen

from tkinter import *
danach folgt ein

Code: Alles auswählen

from tkinter import colorchooser
Vermutlich hab ich es einfach nicht verstanden. Denn warum importiere ich von tkinter zuerst alles und muss danach explizit colorchooser nochmals importieren, damit es verwendet werden kann?


Der ganze Quelltext:

Code: Alles auswählen

from tkinter import *
from tkinter import colorchooser
from tkinter import filedialog
import os
mGui = Tk()
nent = StringVar()
def mhello():
    mtext = nent.get()
    mlabel1 = Label(mGui,text=mtext).pack()
    return

def mNew():
    mlabel3 =  Label(mGui, text="You Clicked New").pack()
    return

def mPath():
    mOspath = os.getcwd()
    messagebox.showinfo(title="You are here...", message=mOspath)
    
    return

def mQuit():
    mExit = messagebox.askyesno(title="Quit", message = "Are you sure?")
    if mExit > 0:
        mGui.destroy()
    return

def mColor():
    mycolor = colorchooser.askcolor()
    mylabel4 = Label(mGui,text=mycolor).pack()
    

mGui.geometry("450x450+200+200")
mGui.title("My Gui")

mlabel = Label(mGui, text="My Label", fg="red", bg="gray").pack()

mbutton = Button(text = "OK", command = mhello).pack()

mEntry = Entry(mGui, textvariable=nent).pack()

#def Menues
menubar = Menu(mGui)

#File Menu
filemenu = Menu(menubar, tearoff = 0)
filemenu.add_command(label="Neu", command = mNew)
filemenu.add_command(label="Open")
filemenu.add_command(label="Save As..")
filemenu.add_command(label="Close", command = mQuit)
filemenu.add_command(label="Color", command = mColor)
menubar.add_cascade(label="File", menu=filemenu)

#SetUp Menu
setupmenu = Menu(menubar,tearoff = 0)
menubar.add_cascade(label="SetUp", menu=setupmenu)

#Help Menu
helpmenu = Menu(menubar, tearoff = 0)
helpmenu.add_command(label="Help Docs")
helpmenu.add_command(label="Current Path", command=mPath)
menubar.add_cascade(label="Help", menu=helpmenu)

mGui.config(menu=menubar)
mGui.mainloop()
BlackJack

@mcdaniels: Du importierst mit dem * alles aus dem `tkinter`-Modul also aus der entsprechenden `__init__.py` von dem Package. Und wenn *die* wiederum nicht das `colorchooser`-Modul importiert, dann ist der Name auch nicht im Namensraum von dem `tkinter`-Modul. Und wenn der Name da nicht drin ist, kann er halt auch mit dem * nicht importiert werden. Arbeite am besten mal die Dokumentation zu Packages durch.

Deine Namensgebung hält sich nicht an PEP8 und sowohl dieser unsinnige `m`-Präfix, als auch die Nummernzusätze am Ende sollten verschwinden. Wozu soll dieser Unsinn denn bitte gut sein? Und was bedeutet `nent`?

Ausserdem möchtest ziemlich sicher nie den Rückgabewert von der `pack()`-Methode an einen Namen binden. Der ist nämlich `None` und da ist ein ``mlabel1 = None`` irgendwie lesbarer. :twisted:

``return`` ohne einen Rückgabewert ganz am Ende von Funktionen ist auch komplett sinnfrei. Die Funktion hört da sowieso auf.

Dann sollten für ein sauberes Programm die Zuweisungen an `mGui` und `nent` und alles nach der `mColor()`-Funktion von der Modulebene in einer Funktion verschwinden. Dann wird nicht mehr alles funktionieren, weil mindestens eine der Funktionen auf einen globalen Wert zugreifen will. Da kommt dann objektorientierte Programmierung ins Spiel.
mcdaniels
User
Beiträge: 168
Registriert: Mittwoch 18. August 2010, 19:53

Hey Blackjack,
ich habe da ein Youtube Tutorial "durchgearbeitet" bzw. besser angeschaut. Es erschien mir Anfangs logisch. Ich weiß, das die Namensgebung nicht in Ordnung ist.

Unterm Strich ist wohl das ganze Beispiel (wiedermal) Mist ;).

Immer wieder die GUI Dinge (die ich besser lassen sollte - ohne OOP-Kenntnisse), aber irgendwie ist es einfach "schöner" in einem GUI zu arbeiten, wie in er Konsole, wenngleich es auch nicht wirklich zielführend zu sein scheint.

LG
Daniel
Antworten