in meinem Python-Programm, um eine Datei ins Internet zu laden, verwende ich einen GTK-Fortschrittsbalken, um den Upload-Fortschritt anzuzeigen. Aber die Probleme, denen man gegenübersteht, sind, dass der Fortschrittsbalken keine Aktivität zeigt, bis der Upload abgeschlossen ist, und dann zeigt er abrupt an, dass der Upload abgeschlossen ist. Ich benutze pycurl, um die HTTP-Anfragen zu machen ... meine Frage ist - Muss ich eine Multithread-Anwendung haben, um die Datei hochzuladen und gleichzeitig die GUI zu aktualisieren? Oder gibt es einen anderen Fehler, den ich mache?
Vielen Dank im Voraus!
Ich zitiere die PyGTK-FAQ :
%Vor%Sie haben einen Fortschrittsbalken in einem Fenster erstellt, dann starten Sie eine Schleife, die etwas Arbeit leistet:
%Vor%Sie werden feststellen, dass das Fenster nicht einmal angezeigt wird, oder wenn der Fortschrittsbalken bis zum Ende der Aufgabe eingefroren bleibt. Die Erklärung ist einfach: gtk ist ereignisgesteuert, und Sie stehlen die Kontrolle von der gtk-Hauptschleife weg und verhindern so, dass normale GUI-Update-Ereignisse verarbeitet werden.
Die einfachste Lösung besteht darin, gtk bei jeder Änderung des Fortschritts vorübergehend die Kontrolle zu geben:
%Vor%Beachten Sie, dass der Benutzer mit dieser Lösung die Anwendung nicht beenden kann (gtk.main_quit würde wegen der neuen Schleife [gtk.main_iteration ()] nicht funktionieren, bis Ihre heavy_work erledigt ist.
Eine andere Lösung besteht darin, gtk-Leerlauffunktionen zu verwenden, die von der gtk-Hauptschleife aufgerufen werden, wenn sie nichts zu tun hat. Daher hat gtk die Kontrolle und die Idle-Funktion muss etwas arbeiten. Es sollte True zurückgeben, wenn mehr Arbeit zu tun ist, andernfalls False.
Die beste Lösung (es hat keine Nachteile) wurde von James Henstridge aufgezeigt. Es nutzt die Generatoren von Python als Leerlauffunktionen, um Python automatisch den Zustand für uns zu erhalten. Es geht so:
Die obige 'while' ist nur ein Beispiel. Die einzigen Regeln sind, dass es nach etwas Arbeit True ergeben sollte, und es gibt mehr Arbeit zu tun, und es muss False ergeben, wenn die Aufgabe erledigt ist.
Mehr als wahrscheinlich ist das Problem, dass Sie in Ihrem Fortschrittsrückruf, bei dem ich vermute, dass Sie den Fortschrittsbalken aktualisieren, keinen Aufruf zur manuellen Aktualisierung der Anzeige machen, d. h. durch die Ereignisschleife der GUI laufen. Dies ist jedoch nur Spekulation, wenn Sie mehr Code bereitstellen können, könnte es einfacher sein, es weiter einzugrenzen.
Der Grund, warum Sie die Anzeige manuell aktualisieren müssen, ist, dass Ihr Haupt-Thread auch den Upload durchführt, wo er blockiert.
Ja, wahrscheinlich benötigen Sie Nebenläufigkeit, und ja Threads sind ein Ansatz, aber wenn Sie Threads verwenden, verwenden Sie bitte eine Methode wie diese: Ссылка , die den Schmerz abstrahieren und dir erlauben wird, sich auf die wichtigen Aspekte zu konzentrieren.
(Ich habe nicht alles in diesem Blogpost durch Faulheit, also Gemeinschaft Wiki) wiederholt.
Eine Möglichkeit, wenn Sie nicht mit pycurl verheiratet sind, besteht darin, IO-Beobachter von GObject zu verwenden.
Damit können Sie den Datei-Upload mit der normalen PyGTK-Ereignisschleife verschachteln und sogar den Aufruf set_progress in Ihrem IO-Watch-Callback ausführen. Wenn Sie die gesamte Arbeit für das Hochladen auf pycurl auslagern, ist das nicht wirklich machbar, aber wenn Sie nur eine Datei über HTTP hochladen, macht io_add_watch die Verwendung eines Sockets für diese auch weniger schmerzhaft.
Tags und Links python user-interface pygtk progress-bar gtk