Frage

in meinem Python-Programm eine Datei im Internet, im mit einem GTK Fortschrittsbalken hochladen, um den Upload-Fortschritt zu zeigen. Aber die Probleme, die mit Blick auf im, sind, dass die Fortschrittsbalken keine Aktivität nicht zeigen, bis der Upload abgeschlossen ist, und dann gibt es plötzlich komplett laden. im mit pycurl die HTTP-Anfragen zu machen ... meine Frage ist - Benötige ich eine Multi-Threaded-Anwendung haben Sie die Datei und gleichzeitig aktualisieren, um die GUI zu laden? oder gibt es eine andere Fehler, die machen IM?

Vielen Dank im Voraus!

War es hilfreich?

Lösung

Ich werde die PyGTK FAQ zitieren :

  

Sie haben einen Fortschrittsbalken in einem Fenster erstellt, dann starten Sie eine Schleife ausgeführt wird, der etwas Arbeit tut:

while work_left:
    ...do something...
    progressbar.set_fraction(...)
  

Sie werden feststellen, dass das Fenster noch nicht angezeigt wird, oder wenn es die Fortschrittsbalken tut bleiben bis zum Ende der Aufgabe eingefroren. Die Erklärung ist einfach:. Gtk ist ereignisgesteuert, und Sie stehlen Kontrolle weg von der GTK-Hauptschleife, so dass es bei der Verarbeitung von normalen GUI Update-Ereignissen zu verhindern

     

Die einfachste Lösung besteht darin, auf vorübergehend geben Kontrolle jedes Mal gtk wieder der Fortschritt wird geändert:

while work_left:
    ...do something...
    progressbar.set_fraction(...)
    while gtk.events_pending():
        gtk.main_iteration()
  

Beachten Sie, dass mit dieser Lösung kann der Benutzer die Anwendung beenden (gtk.main_quit würde wegen der neuen Schleife nicht funktionieren [gtk.main_iteration ()]), bis Ihre heavy_work gemacht wird.

     

Eine andere Lösung besteht zur Verwendung von GTK Leerlauf-Funktionen, die durch die gtk Hauptschleife aufgerufen werden, wenn es nichts zu tun hat. Daher ist gtk in der Steuerung, und die Leerlauffunktion ein wenig Arbeit zu tun. Es sollte Wahr zurück, wenn es mehr Arbeit getan werden, sonst Falsch.

     

Die beste Lösung (es hat keine Nachteile) wurde von James Henstridge hingewiesen. Es nutzt Python-Generatoren als Leerlauf-Funktionen, Python automatisch erhält den Zustand für uns zu machen. Es geht so:

def my_task(data):
    ...some work...
    while heavy_work_needed:
        ...do heavy work here...
        progress_label.set_text(data) # here we update parts of UI
        # there's more work, return True
        yield True
    # no more work, return False
    yield False

def on_start_my_task_button_click(data):
    task = my_task(data)
    gobject.idle_add(task.next)
  

Die ‚while‘ oben ist nur ein Beispiel. Die einzigen Regeln sind, dass es nachdem ich ein bisschen Arbeit Wahr ergeben sollte und es gibt noch mehr Arbeit zu tun, und es muss Falsch ergeben, wenn die Aufgabe erledigt ist.

Andere Tipps

Mehr als wahrscheinlich das Problem ist, dass Rückruf in Ihren Fortschritt, das ist, wo ich Sie Aktualisierung des Fortschrittsbalken vermuten, dass Sie nicht einen Anruf manuell die Anzeige aktualisieren das heißt durch die Ereignisschleife GUI laufen. Dies ist nur Spekulation aber, wenn Sie mehr Code zur Verfügung stellen können, könnte es einfacher sein, es zu verengen weiter.

Der Grund müssen Sie manuell die Anzeige aktualisieren ist, weil Ihr Hauptthread auch den Upload durchführt, das ist, wo es blockiert wird.

In Python 2.x integer Operanden führen in Integer-Division. Versuchen Sie folgendes:

#Callback function invoked when download/upload has progress
def progress(download_t, download_d, upload_t, upload_d):
    print 'in fileupload progress'
    mainwin.mainw.prog_bar.set_fraction(float(upload_d) / upload_t)

Ja, müssen Sie wahrscheinlich Gleichzeitigkeit, und ja Threads sind ein Ansatz, aber wenn Sie Threads zu tun, verwenden Sie bitte ein Verfahren wie dieses: http://unpythonic.blogspot.com/2007/08/using-threads-in-pygtk.html die wird abstrahieren die Schmerzen und ermöglicht es Ihnen, sich auf die wichtigen Aspekte zu konzentrieren.

(Ich habe nicht alles in dieser Blog-Post durch Faulheit wiederholt, damit Community Wiki).

Eine Option, wenn Sie nicht verheiratet sind zu pycurl ist GObject des IO-Beobachter zu verwenden.

http://pygtk.org/ pygtk2reference / gobject-functions.html # funktions gobject - io-Add-sehen

Diese können Sie in den Datei-Upload mit der normalen PyGTK Ereignisschleife verschachteln, und sogar das set_progress Telefonieren Rückruf in Ihrem IO-Uhr. Wenn Sie die ganze Arbeit sind Offloading für das Hochladen auf pycurl das ist nicht wirklich machbar, aber wenn Sie nur eine Datei über HTTP hochladen, wird io_add_watch für eine Steckdose machen mit so viel weniger schmerzhaft als gut.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top