Pergunta

no meu programa python para fazer upload de um arquivo para a internet, mensagens instantâneas usando uma barra de progresso GTK para mostrar o progresso do upload. Mas os problemas que im enfrentando é que a barra de progresso não mostra qualquer atividade até que o upload estiver concluído, e então abruptamente indica carregar completa. im usando pycurl para fazer as solicitações http ... minha pergunta é - que eu preciso para ter uma aplicação multi-threaded para carregar o arquivo e, simultaneamente, atualizar o gui? ou há algum outro erro que im fazendo?

Agradecemos antecipadamente!

Foi útil?

Solução

Vou citar o PyGTK FAQ :

Você criou uma barra de progresso dentro de uma janela, então você começar a correr um loop que faz algum trabalho:

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

Você vai notar que a janela não mesmo aparecer, ou se ele faz as estadias barra de progresso congelados até o fim da tarefa. A explicação é simples: gtk é orientado a eventos, e você está roubando o controle de distância do loop principal do GTK, assim, impedindo-a de processamento de eventos normais de atualização GUI

.

A solução mais simples consiste em dar temporariamente o controle para gtk cada vez que o progresso é alterado:

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

Observe que com esta solução, o usuário não pode sair do aplicativo (Gtk.main_quit não iria funcionar por causa da nova malha [gtk.main_iteration ()]) até que seu heavy_work é feito.

Outra solução consiste na utilização de funções ociosas GTK, que são chamados pelo gtk loop principal sempre que ele não tem nada a fazer. Portanto, gtk está no controle, e a função ocioso tem que fazer um pouco de trabalho. Ele deve retornar True se há mais trabalho a ser feito, caso contrário, False.

A melhor solução (ele não tem inconvenientes) foi apontado por James Henstridge. Ele está se aproveitando de geradores de Python como funções ociosas, para fazer python automaticamente preservar o estado para nós. Ele vai como esta:

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)

O 'enquanto' acima é apenas um exemplo. As únicas regras são que ele deve render verdadeiro depois de fazer um pouco de trabalho e não há mais trabalho a fazer, e deve produzir False quando a tarefa é feita.

Outras dicas

Mais do que provavelmente a questão é que, em seu retorno de progresso, que é onde eu presumo que você está atualizando a barra de progresso, você não está fazendo uma chamada para atualizar manualmente a exibição ou seja executado através ciclo de eventos do GUI. Este é apenas especulação, porém, se você pode fornecer mais de código, pode ser mais fácil para reduzi-lo ainda mais.

A razão que você precisa atualizar manualmente a exibição é porque seu segmento principal também está realizando o upload, que é onde ele está bloqueando.

Em Python 2.x inteiro operandos resultado na divisão inteira. Tente isto:

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

simultaneidade Sim, você provavelmente precisa, e sim tópicos são uma abordagem, mas se você fizer uso de fios, use um método como este: http://unpythonic.blogspot.com/2007/08/using-threads-in-pygtk.html que vai abstrair o dor, e permitem que você se concentrar nos aspectos importantes.

(eu não ter repetido tudo nesse post por preguiça, daí comunidade wiki).

Uma opção, se você não está casado com pycurl, é a utilização de observadores IO do GObject.

http://pygtk.org/ pygtk2reference / gobject-functions.html # função-gobject - io-add-relógio

Usando isso, você pode intercalar o upload do arquivo com o ciclo de eventos PyGTK normal, e até mesmo fazer a chamada set_progress em seu relógio callback IO. Se você está transferindo todo o trabalho para fazer o upload para pycurl isso não é realmente viável, mas se você está apenas upload de um arquivo via HTTP, io_add_watch fará usando um soquete para este muito menos doloroso também.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top