Domanda

nel mio programma Python per caricare un file su Internet, sto usando una barra di avanzamento GTK per mostrare l'avanzamento del caricamento. Ma il problema che sto affrontando è che la barra di avanzamento non mostra alcuna attività fino al completamento del caricamento, quindi indica bruscamente il caricamento completato. sto usando pycurl per fare le richieste http ... la mia domanda è - devo avere un'applicazione multi-thread per caricare il file e aggiornare contemporaneamente la GUI? o c'è qualche altro errore che sto facendo?

Grazie in anticipo!

È stato utile?

Soluzione

Citerò il PyGTK FAQ :

  

Hai creato una barra di avanzamento all'interno di una finestra, quindi inizi a eseguire un ciclo che funziona in qualche modo:

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

Noterai che la finestra non viene nemmeno visualizzata o, se lo fa, la barra di avanzamento rimane bloccata fino alla fine dell'attività. La spiegazione è semplice: gtk è guidato dagli eventi e stai rubando il controllo al loop principale di gtk, impedendogli così di elaborare i normali eventi di aggiornamento della GUI.

     

La soluzione più semplice consiste nel restituire temporaneamente il controllo a GTK ogni volta che si modifica l'avanzamento:

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

Si noti che con questa soluzione, l'utente non può chiudere l'applicazione (gtk.main_quit non funzionerebbe a causa del nuovo ciclo [gtk.main_iteration ()]) fino a quando il lavoro pesante non viene eseguito.

     

Un'altra soluzione consiste nell'utilizzare le funzioni inattive di gtk, che vengono chiamate dal ciclo principale di gtk ogni volta che non ha nulla a che fare. Pertanto, gtk ha il controllo e la funzione inattiva deve fare un po 'di lavoro. Dovrebbe restituire True se c'è altro lavoro da fare, altrimenti False.

     

La soluzione migliore (non ha inconvenienti) è stata indicata da James Henstridge. Sta sfruttando i generatori di Python come funzioni inattive, per far sì che Python preservi automaticamente lo stato per noi. Va così:

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)
  

Il 'while' sopra è solo un esempio. Le uniche regole sono che dovrebbe produrre True dopo aver fatto un po 'di lavoro e c'è ancora molto lavoro da fare, e deve produrre False quando l'attività è terminata.

Altri suggerimenti

Molto probabilmente il problema è che nel callback dei tuoi progressi, che presumo tu stia aggiornando la barra di avanzamento, non stai effettuando una chiamata per aggiornare manualmente il display, cioè attraverso il ciclo degli eventi della GUI. Questa è solo una speculazione, tuttavia, se è possibile fornire più codice, potrebbe essere più semplice restringerlo ulteriormente.

Il motivo per cui devi aggiornare manualmente il display è perché anche il tuo thread principale sta eseguendo il caricamento, che è dove sta bloccando.

Negli operandi interi di Python 2.x si ottiene una divisione di numeri interi. Prova questo:

#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ì, probabilmente hai bisogno di concorrenza, e sì i thread sono un approccio, ma se usi i thread, utilizza un metodo come questo: http://unpythonic.blogspot.com/2007/08/using-threads-in-pygtk.html che astrarrà dolore e ti permettono di concentrarti sugli aspetti importanti.

(Non ho ripetuto tutto in quel post sul blog per pigrizia, quindi wiki della community).

Un'opzione, se non sei sposato con pycurl, è usare gli osservatori IO di GObject.

http://pygtk.org/ pygtk2reference / gobject-functions.html # function-gobject - io-aggiungere-guardare

Usando questo è possibile interlacciare il caricamento del file con il normale ciclo di eventi PyGTK e persino eseguire la chiamata set_progress nel callback di IO watch. Se stai scaricando tutto il lavoro per il caricamento su Pycurl, questo non è davvero fattibile, ma se stai solo caricando un file su HTTP, io_add_watch renderà l'utilizzo di un socket anche per questo molto meno doloroso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top