Pregunta

en mi programa de Python para cargar un archivo a Internet, estoy usando una barra de progreso GTK para mostrar el progreso de carga. Pero el problema que enfrento es que la barra de progreso no muestra ninguna actividad hasta que se completa la carga, y luego indica abruptamente que la carga se ha completado. estoy usando pycurl para hacer las solicitudes http ... mi pregunta es - ¿Necesito tener una aplicación multiproceso para cargar el archivo y actualizar simultáneamente la interfaz gráfica de usuario? ¿O hay algún otro error que estoy cometiendo?

¡Gracias de antemano!

¿Fue útil?

Solución

Voy a citar el PyGTK Preguntas frecuentes :

  

Ha creado una barra de progreso dentro de una ventana, luego comienza a ejecutar un bucle que funciona:

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

Notarás que la ventana ni siquiera aparece, o si lo hace, la barra de progreso permanece congelada hasta el final de la tarea. La explicación es simple: gtk está controlado por eventos y está robando el control del bucle principal de gtk, evitando así que procese eventos normales de actualización de la GUI.

     

La solución más simple consiste en devolver temporalmente el control a gtk cada vez que se cambia el progreso:

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

Observe que con esta solución, el usuario no puede salir de la aplicación (gtk.main_quit no funcionaría debido al nuevo bucle [gtk.main_iteration ()]) hasta que termine su trabajo pesado.

     

Otra solución consiste en utilizar las funciones inactivas de gtk, que son llamadas por el bucle principal de gtk cuando no tiene nada que hacer. Por lo tanto, gtk tiene el control y la función inactiva tiene que hacer un poco de trabajo. Debería devolver True si hay más trabajo por hacer, de lo contrario, False.

     

James Henstridge señaló la mejor solución (no tiene inconvenientes). Está aprovechando los generadores de Python como funciones inactivas, para hacer que Python conserve automáticamente el estado para nosotros. Va así:

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)
  

El 'while' anterior es solo un ejemplo. Las únicas reglas son que debe producir Verdadero después de hacer un poco de trabajo y hay más trabajo por hacer, y debe producir Falso cuando se realiza la tarea.

Otros consejos

Es muy probable que el problema sea que en su devolución de llamada de progreso, que es donde supongo que está actualizando la barra de progreso, no está haciendo una llamada para actualizar manualmente la pantalla, es decir, ejecutar el bucle de eventos de la GUI. Sin embargo, esto es solo especulación, si puede proporcionar más código, podría ser más fácil reducirlo aún más.

La razón por la que necesita actualizar manualmente la pantalla es porque su hilo principal también está realizando la carga, que es donde está bloqueando.

En python 2.x, los operandos enteros dan como resultado una división entera. Prueba esto:

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

Sí, probablemente necesite concurrencia, y sí, los hilos son un enfoque, pero si usa hilos, utilice un método como este: http://unpythonic.blogspot.com/2007/08/using-threads-in-pygtk.html que abstraerá dolor, y le permite centrarse en los aspectos importantes.

(No he repetido todo en esa publicación de blog a través de la pereza, de ahí el wiki de la comunidad).

Una opción, si no está casado con pycurl, es utilizar los observadores IO de GObject.

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

Con esto, puede intercalar la carga del archivo con el bucle de evento PyGTK normal e incluso hacer la llamada set_progress en su devolución de llamada de observación IO. Si está descargando todo el trabajo para cargar en pycurl, esto no es realmente factible, pero si solo está cargando un archivo a través de HTTP, io_add_watch hará que usar un socket para esto sea mucho menos doloroso también.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top