(GUI Tkinter) Dateipfad-Eingabe an Code übergeben?

Fragen zu Tkinter.
Antworten
MarcNAV
User
Beiträge: 52
Registriert: Freitag 16. Mai 2014, 11:39

Habe folgendes Problem und hab durch längeres Googlen keine Lösung gefunden.
Ich hätte gern ein Fenster mit einer Eingabezeile (Dateipfad) und einen Run-Knopf welcher mir dann die Dateien im angegeben Pfad entpackt. Der def zip() Code funktioniert auf jeden Fall.
Wie übergebe ich den Pfad im entry.feld des Pop-up Fensters an Zeile 6?

Code: Alles auswählen

import gzip, os
import Tkinter as tk

def zip():

    root_path = eingabe
    extension = '.gz'
    for path, _, filenames in os.walk(root_path):
        for filename in filenames:
            if filename.endswith(extension):
                a = os.path.abspath(os.path.join(path, filename))

                #.gz entpacken
                in_file = a
                try:
                    inF = gzip.open(a, 'rb')
                    newfile = os.path.join(path, (os.path.basename(filename))[:-2])
                    outF = open(newfile , 'wb')
                    outF.write( inF.read() )
                    inF.close()
                    outF.close()
                    print 'Unpacked: ' + filename
                    os.unlink(in_file)              #.gz Datei loeschen
                except:
                    pass
                    print 'Unpacking: ' + filename + ' failed'


def main():

    #Pop-up Fenster
    w =tk.Tk()
    w.title('GZIP')
    w.geometry('300x200')

    #Workspace Beschriftung
    l = tk.Label(w, text = 'Workspace:')
    l.place(x= 10, y = 100)

    #Eingabefeld Pfad
    e = tk.Entry(w, width=35)
    e.place(x=80, y=100)
    eingabe = e.get()

    #Button
    b = tk.Button(w, text = 'Run', command= zip)
    b.place(x=135 ,y= 50)

    w.mainloop()

if __name__ == '__main__':
    main()


Noch ne Zusatzfrage: Was macht eigentlich der .pack() Befehl in Tkinter?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Einfach als Parameter der Funktion. In Zeile 46 müsstest du dann noch den Aufruf entsprechen anpassen:

Code: Alles auswählen

tk.Button(w, text='Run', command=lambda: decompress(eingabe.get()))
An deinem Code gibt es aber noch einiges zu verbessern. Als erstes fällt natürlich auf, dass der Name der Funktion schlecht gewählt ist. Python hat in den built-in-Funktionen bereits eine Funktion mit dem Namen "zip", die verdeckst du mit deiner Funktion. Da die zip-Funktion recht häufig verwendet wird, kann das zu unschönen Problemen führen.

Als nächstes fällt natürlich auf, dass deine Funktion nichts komprimiert, sonder genau das Gegenteil tut. Es entpackt ein Archiv. Da ist "zip" doch ein sehr irreführender Name. Nenne die Funktion doch einfach "decompress".

Die Angabe der Dateiendung in Zeile 7 ist eine Konstante, daher sollte der Namen durchgängig groß geschrieben werden. Da die Dateiendung in jedem Aufruf gleich ist, solltest du die Definition der Konstante aus der Funktion herausziehen.

Der Name "a" in Zeile 11 ist reichlich nichtssagend, die Zeile 14 ist total nutzlos. Du kannst in Zeile 11 gleich den Rückgabewert an "in_file" binden.

Du hast wieder einen try-except-Block welcher alle Fehler abfängt. Behandle nur die Ausnahmen, welche du auch tatsächlich behandeln kannst. Andernfalls werden möglicherweise sogar Programmierfehler verdeckt oder dein Programm befindet sich in einem ungültigen Zustand. Wenn ein Programm eine Ausnahme nicht behandeln kann, dann darf es das auch nicht tun. Dann muss es crashen, alles andere endet in einem Unglück. Hinzu kommt noch, dass du die Fehlermeldung einfach verschluckst, wie will man da einen Fehler finden?

Du solltest Dateien mittels with-Statement öffnen, dann werden die auch wieder korrekt geschlossen. In deinem Fall hast du sonst möglicherweise diverse Dateihandles rumfliegen.

Die -2 in Zeile 17 ist keine gute Idee. Einfach so Konstanten im Programm einführen ist eine sehr beliebte Fehlerquelle. Wenn man irgendwo etwas ändern muss, müssen sonst ggf. diverse Konstanten angepasst werden. Das ist nicht nur viel Arbeit und schwer nachzuvollziehen, sondern vorallem führt es dazu, dass man Änderungen vergisst. Du musst dir überlegen: Woher kommt die -2 und wie berechnest du sie.

Die ganzen Platzierungen der Widgets mittels place solltest du dir abgewöhnen, damit sieh die GUI nur auf deinem Rechner vernünftig aus. Aber auch nur so lange du nichts an der Schriftart, Schriftgröße oder Seitenabständen änderst. Bei einem neuen Monitor kann das ganze schon zu Problemen führen, auf anderen Systemen wird es in der Regel total gruselig aussehen. Verwende also pack oder grid. Dazu gibt es auch einen Abschnitt in der Dokumentation zu Tkinter.
Das Leben ist wie ein Tennisball.
MarcNAV
User
Beiträge: 52
Registriert: Freitag 16. Mai 2014, 11:39

Müsste es nicht so funktionieren? So übergibt doch die Main-Funktion "eingabe" an die Decompress-Funktion oder? ich bekomme aber immer den Fehler: decompress() takes no arguments (1 given). Füge ich Zeile 46 decompress(eingabe.get()) ein dann kommt als Fehler: 'str' object has no attribute 'get'
Mmmh :K

Code: Alles auswählen

import gzip, os
import Tkinter as tk

def decompress():

    root_path = eingabe
    extension = '.gz'
    for path, _, filenames in os.walk(root_path):
        for filename in filenames:
            if filename.endswith(extension):
                in_file = os.path.abspath(os.path.join(path, filename))

                #.gz entpacken
                try:
                    inF = gzip.open(in_file, 'rb')
                    newfile = os.path.join(path, (os.path.basename(filename))[:-len(extension)])
                    outF = open(newfile , 'wb')
                    outF.write( inF.read() )
                    inF.close()
                    outF.close()
                    print 'Unpacked: ' + filename
                    os.unlink(in_file)              #.gz Datei loeschen
                except:
                    pass
                    print 'Unpacking: ' + filename + ' failed'


def main():

    #Pop-up Fenster
    w =tk.Tk()
    w.title('GZIP')
    w.geometry('300x200')

    #Workspace Beschriftung
    l = tk.Label(w, text = 'Workspace:')
    l.place(x= 10, y = 100)

    #Eingabefeld Pfad
    e = tk.Entry(w, width=35)
    e.place(x=80, y=100)
    eingabe = e.get()

    #Button
    b = tk.Button(w, text = 'Run', command=lambda: decompress(eingabe))
    b.place(x=135 ,y= 50)

    w.mainloop()

if __name__ == '__main__':
    main()





Zuletzt geändert von MarcNAV am Montag 7. Juli 2014, 13:42, insgesamt 2-mal geändert.
BlackJack

@MarcNAV: Ja die `main()`-Funktion *übergibt* den Wert von `eingabe` aber die `decompress()`-Funktion erwartet gar keine Argumente. Genau das sagt Dir die Fehlermeldung ja auch. In der `decompress()` wäre dann auch gleich der Name `eingabe` ein Problem: Wo kommt der Wert für diesen Namen her?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Die Fehlermeldung sagt es dir doch schon: Die decompress-Funktion bekommt einen Parameter, sie erwartet aber keinen. Wenn du einer Funktion etwas übergeben willst, dann musst du natürlich auch das Argument in der Definition def Funktion angeben.

``decompress(eingabe.get())`` muss natürlich ``decompress(e.get())`` heißen.
Das Leben ist wie ein Tennisball.
MarcNAV
User
Beiträge: 52
Registriert: Freitag 16. Mai 2014, 11:39

Noch mal zur Verständlichkeit, weils mich auch selbst verwirrt:D
@BlackJack: ich möchte ein Fenster erzeugen, das so aussieht:
-----------------------------------
Workspace: "Dateipfad"
"Run"-Button
-----------------------------------

nun kopiere ich einen Dateipfad in das Workspace-Eingabefeld und möchte, dass er mir den Dateipfad an Zeile 6 in der decompress() funktion übergibt, da mit Betätigen des Run-Buttons eben diese Funktion gestartet wird.
MarcNAV
User
Beiträge: 52
Registriert: Freitag 16. Mai 2014, 11:39

Wäre einer so nett und könnte mir den kompletten Code mal an den besagten stellen abändern? Komm grad komplett durcheinander mit e.get() und eingabe und wer was übergibt.
MarcNAV
User
Beiträge: 52
Registriert: Freitag 16. Mai 2014, 11:39

Ganz vereinfacht, wo ist da der Logikfehler?

Code: Alles auswählen

def decompress():
    root_path = e.get()
    dosomething()

def main():

    #Eingabefeld
    e = tk.Entry(w, width=35)
    e.get()

    #Button
    b = tk.Button(w, text = 'Run', command= lambda: decompress(e.get()))

if __name__ == '__main__':
    main()

Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

MarcNAV hat geschrieben:Ganz vereinfacht, wo ist da der Logikfehler?
Du greifst in decompress auf e.get() zu. e gibt es aber nicht im Namensraum von decompress.

Warum verwendest du dort überhaupt e? Du übergibst doch den Wert in der lambda-Funktion. decompress benötigt nun natürlich einen Parameter der den übergebenen Wert aufnimmt.

Code: Alles auswählen

def decompress(root_path):
    print(root_path)
MarcNAV
User
Beiträge: 52
Registriert: Freitag 16. Mai 2014, 11:39

Danke /me. Wenn ich root_path printe, dann gibt er mir die Eingabe aus. Das funktioniert schon mal.
Aber wenn ich Run drücke, macht das Programm nichts. Den Pfad gebe ich natürlich in der Form 'F:/Test/......' im eingabefenster ein. Wenn ich in der decompress() Funktion den root_path manuell eingebe macht das Programm was es soll. Weiß echt nicht wo der Fehler liegt.
Fruststrating:(

Code: Alles auswählen

import gzip, os
import Tkinter as tk

def decompress(root_path):
    
    print root_path
    extension = '.gz'
    for path, _, filenames in os.walk(root_path):
        for filename in filenames:
            if filename.endswith(extension):
                in_file = os.path.abspath(os.path.join(path, filename))

                #.gz entpacken
                try:
                    inF = gzip.open(in_file, 'rb')
                    newfile = os.path.join(path, (os.path.basename(filename))[:-len(extension)])
                    outF = open(newfile , 'wb')
                    outF.write( inF.read() )
                    inF.close()
                    outF.close()
                    print 'Unpacked: ' + filename
                    os.unlink(in_file)              #.gz Datei loeschen
                except:
                    pass
                    print 'Unpacking: ' + filename + ' failed'


def main():

    #Pop-up Fenster
    w =tk.Tk()
    w.title('GZIP')
    w.geometry('300x200')

    #Workspace Beschriftung
    l = tk.Label(w, text = 'Workspace:')
    l.place(x= 10, y = 100)

    #Eingabefeld Pfad
    e = tk.Entry(w, width=35)
    e.get()
    e.place(x=80, y=100)


    #Button
    b = tk.Button(w, text = 'Run', command= lambda: decompress(e.get()))
    b.place(x=135 ,y=50)

    w.mainloop()

if __name__ == '__main__':
    main()


Antworten