Multiprozess oder Multithreading in Tkinter für Filedownload- Statusanzeige.

Fragen zu Tkinter.
Antworten
Benutzeravatar
Miscelo
User
Beiträge: 15
Registriert: Sonntag 2. Februar 2020, 21:39

Hallo Forumer,

Ich baue gerade eine kleine GUI für mich die dazu dient Dateien herunterzuladen.
Hierzu gibt es ein Entry mit Downloadpfad und ein weiteres Entry mit der Netzwerk-Adresse. Also http://...

Per Knopfdruck soll der Download erfolgen.
Ich würde ganz gern eine Anzeige einbauen, die den aktiven Download anzeigt.
Es muss auch kein Statusbalken sein. Eine blinkende Downloadschrift macht es bei mir.
Allerdings meine Frage:
Mein Ansatz war Multiprocessing um dieses zu bewerkstelligen, allerdings habe ich keine Ahnung ob es nötig ist.

Ich habe mein Script zusammengekürzt damit es verständlicher ist. Hoffentlich habe ich es erreicht. :?

Code: Alles auswählen

from multiprocessing import Process
import tkinter as tk
import urllib3
import requests


class MyWindow:
    def __init__(self, master):
        self.colors = {"green": "#22cf00", "bg":"#1a1a1a", "fg":"#3c3c3c"}
        fm = tk.Frame(master)
        fm.pack()
        self.entry = tk.Entry(fm)
        self.entry.pack(pady=20)
        self.label = tk.Label(fm, text="Waiting for you!", background=self.colors["bg"], foreground=self.colors["fg"])
        self.label.pack(pady=10)
        self.btn = tk.Button(fm, text="click me", command=self.func)
        self.btn.pack(pady=10)

    # Funktion download file from http
    def func(self):
        print("Hello", arg)
        url = 'http://www.tgcomes.es/CONIL-VEJER-BARB-ZAHARA.pdf'     # Testfile 
        requests.get(url, stream=True)

        # flash label
    def flash(self, arg):
        print("Hello", arg)
        self.label.config(text=arg)
        #bg = self.label.cget("background")
        #fg = self.label.cget("foreground")
        #self.label.configure(background=fg, foreground=bg)
        #root.after(1000, self.flash)


    def multiproc(self):  
        self.p = Process(target=self.func, args=("World!",))
        self.q = Process(target=self.flash, args=("Universe!",))
        self.p.start()
        self.q.start()
        self.p.join()
        self.q.join()
        self.label.configure(text="Finish")


if __name__ == "__main__":
    root = tk.Tk()
    myapp = MyWindow(root)
    root.title("test")
    root.geometry("200x200")
    root.mainloop()
Findet ihr den Ansatz richtig, wenn es auch noch verbesserungswürdig ist. Oder ist es besser von der verwendeten Downloadfunktion sich einen Rückgabewert zu erzeugen. WEnn ich auch noch nicht weis wie. Mutlithreating ist glaub ich mit Kanonen auf Spatzen schießen.
Danke für eure Hilfe im voraus.
# Don't Panik!
answer = lambda x: 42
answer("question")
Benutzeravatar
__blackjack__
User
Beiträge: 14087
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Miscelo: Ich würde ja eher sagen das `multiprocessing` hier die Kanonen auf Spatzen sind. Da reicht ein Thread für den Download der den Fortschritt über eine `queue.Queue` an die GUI übermittelt, die per `after()` regelmässig in diese Queue schaut. Wichtig: Nicht aus einem anderen Thread ausser dem in dem die GUI-Hauptschleife läuft, die GUI manipulieren. Das mag vielleicht so aussehen als wenn das ginge, aber das kann auch katastrophal schief gehen, denn GUI-Rahmenwerke sind im allgemeinen nicht thread-sicher.

In `tkinter.ttk` gibt es eine `Progressbar` die man verwenden kann. Wobei man schauen muss, das es sowohl Downloads geben kann, bei denen man die Anzahl der Bytes mitgeteilt bekommt, also einen normalen Fortschrittsbalken darstellen kann, als auch welche wo die Anzahl der Bytes nicht am Anfang ermittelt werden kann. Beides kann `Progressbar`.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
Miscelo
User
Beiträge: 15
Registriert: Sonntag 2. Februar 2020, 21:39

WOW!. Danke für die schnelle und ausfürliche Antwort. Du hast mir ein paar tolle Begriffe zum Nachlesen gegeben.
Dann werde ich es versuchen so anzugehen, wie du es mir beschrieben hast.
Jetzt mach ich mich mal ran ans duckduckgoen.
Dann erkläre ich den Thread vorerst für beendet.
# Don't Panik!
answer = lambda x: 42
answer("question")
Antworten