Question

dans mon programme python pour télécharger un fichier sur Internet, utilisez une barre de progression GTK pour afficher la progression du téléchargement. Mais le problème auquel je suis confronté est que la barre de progression ne montre aucune activité tant que le téléchargement n'est pas terminé, puis indique soudainement que le téléchargement est terminé. im utilisant pycurl pour faire les requêtes http ... ma question est - Ai-je besoin d'une application multithread pour charger le fichier et mettre à jour simultanément l'interface graphique? ou y a-t-il une autre erreur que je fais?

Merci d'avance!

Était-ce utile?

La solution

Je vais citer le PyGTK FAQ :

  

Vous avez créé une barre de progression dans une fenêtre, puis vous commencez à exécuter une boucle qui fonctionne:

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

Vous remarquerez que la fenêtre n'apparaît même pas ou, si c'est le cas, la barre de progression reste figée jusqu'à la fin de la tâche. L’explication est simple: gtk est piloté par les événements et vous dérobez le contrôle à la boucle principale de gtk, l’empêchant ainsi de traiter les événements de mise à jour de l’interface graphique normale.

     

La solution la plus simple consiste à rendre temporairement le contrôle à gtk à chaque changement de progression:

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

Notez qu'avec cette solution, l'utilisateur ne peut pas quitter l'application (gtk.main_quit ne fonctionnerait pas à cause d'une nouvelle boucle [gtk.main_iteration ()]) tant que votre travail lourd n'est pas terminé.

     

Une autre solution consiste à utiliser les fonctions inactives de gtk, appelées par la boucle principale de gtk chaque fois que cela n’a rien à faire. Par conséquent, gtk est en contrôle et la fonction inactive doit faire un peu de travail. Il devrait retourner True s'il reste du travail à faire, sinon False.

     

La solution la plus adaptée (sans aucun inconvénient) a été soulignée par James Henstridge. Il tire parti des générateurs de python en tant que fonctions inactives pour que python préserve automatiquement l’état pour nous. Cela va comme ceci:

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)
  

Le "tant que" ci-dessus n'est qu'un exemple. Les seules règles sont que cela doit rapporter True après un peu de travail et qu'il reste encore du travail à faire et que cela doit donner False lorsque la tâche est terminée.

Autres conseils

Le problème est probablement lié au fait que, dans votre rappel de progression, où je suppose que vous mettez à jour la barre de progression, vous n'appelez pas pour mettre à jour manuellement l'affichage, c'est-à-dire exécuter la boucle d'événement de l'interface graphique. Ce n'est que spéculation, cependant, si vous pouvez fournir plus de code, il sera peut-être plus facile de le réduire davantage.

La raison pour laquelle vous devez mettre à jour manuellement l'affichage est parce que votre thread principal effectue également le téléchargement, qui est l'endroit où il se bloque.

En python 2.x, les opérandes entiers entraînent une division en nombre entier. Essayez ceci:

#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)

Oui, vous avez probablement besoin de la concurrence et oui, les threads sont une approche, mais si vous utilisez des threads, utilisez une méthode comme celle-ci: http://unpythonic.blogspot.com/2007/08/using-threads-in-pygtk.html qui résumera les souffrir et vous permettre de vous concentrer sur les aspects importants.

(Je n'ai pas tout répété dans ce billet de blog via la paresse, d'où le wiki de la communauté).

Si vous n'êtes pas marié à Pycurl, vous pouvez utiliser les observateurs d’OI de GObject.

http://pygtk.org/ pygtk2reference / gobject-functions.html # function-gobject - io-add-watch

Cette opération vous permet d'entrelacer le téléchargement de fichier avec la boucle d'événement PyGTK normale et même d'effectuer l'appel set_progress dans votre rappel de surveillance IO. Si vous déchargez tout le travail de téléchargement sur pycurl, ce n'est pas vraiment faisable, mais si vous ne chargez qu'un fichier via HTTP, io_add_watch rendra l'utilisation d'un socket beaucoup moins pénible.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top