Pergunta

Eu escrevi um script python para processar alguns dados dos arquivos CSV. O script leva entre 3 a 30 minutos para ser concluído, dependendo do tamanho do CSV.

Agora eu quero colocar uma interface da Web para isso, para que eu possa fazer o upload dos arquivos de dados CSV de qualquer lugar. Escrevi uma página básica de upload de postagem HTTP e usei o módulo CGI do Python - mas o script apenas depois de algum tempo.

O script produz cabeçalhos HTTP no início e produz bits de dados depois de iterar em todas as linhas do CSV. Como exemplo, essa declaração de impressão acionaria a cada 30 segundos ou mais.

# at the very top, with the 'import's
print "Content-type: text/html\n\n Processing ... <br />"

# the really long loop.
for currentRecord in csvRecords:
    count = count + 1
    print "On line " + str(count) + " <br />"

Presumi que o navegador receberia os cabeçalhos e esperaria, pois continua recebendo pequenos pedaços de dados. Mas o que realmente parece acontecer é que não recebe nenhum dado e Error 504 vezes quando recebeu um CSV com muitas linhas.

Talvez haja algum cache acontecendo em algum lugar? Dos troncos,

[Wed Jan 20 16:59:09 2010] [error] [client ::1] Script timed out before returning headers: datacruncher.py, referer: http://localhost/index.htm
[Wed Jan 20 17:04:09 2010] [warn] [client ::1] Timeout waiting for output from CGI script /Library/WebServer/CGI-Executables/datacruncher.py, referer: http://localhost/index.htm

Qual é a melhor maneira de resolver isso, ou, não é apropriado executar esses scripts em um navegador?

Editar:Este é um script para meu próprio uso - normalmente pretendo usá -lo no meu computador, mas achei que uma interface baseada na Web poderia ser útil durante a viagem ou, por exemplo, de um telefone. Além disso, não há realmente nada a baixar - o script provavelmente enviará um relatório por e -mail no final.

Foi útil?

Solução

Eu separaria o trabalho assim:

  1. Um URL do aplicativo da Web que aceita o arquivo CSV publicado. O aplicativo da Web coloca o conteúdo do CSV em uma fila off -line, por exemplo, uma tabela de banco de dados. A resposta do aplicativo da web deve ser um ID exclusivo para o item na fila (use uma coluna de ID de incremento automático, por exemplo). O cliente deve armazenar este ID para a Parte 3.

  2. Um aplicativo de serviço independente que faz a fila do trabalho e faz o processamento. Após a conclusão do processamento, armazene os resultados em outra tabela de banco de dados, usando o ID exclusivo como chave.

  3. Um URL de aplicativo da web que pode obter resultados processados, http://server/getresults/uniqueid/. Se o processamento for concluído (ou seja, o ID exclusivo for encontrado na tabela de banco de dados de resultados), retorne os resultados. Se não for concluído, a resposta deve ser um código que indique isso. Por exemplo, um cabeçalho HTTP personalizado, uma resposta de status HTTP, corpo de resposta 'pendente' ou similar.

Outras dicas

Eu já tive essa situação antes e usei Cronjobs. O script HTTP apenas escreveria em uma fila um trabalho a ser executado (um db ou um arquivo em um diretório) e o Cronjob o lia e executou esse trabalho.

Você provavelmente precisará fazer um stdout.flush(), pois o script ainda não está escrevendo nada no servidor da web até que você tenha escrito o valor de dados de um buffer de página - o que não acontece antes do tempo limite.

Mas a maneira correta de resolver isso é, como outros sugeriram, fazer o processamento em um thread/processo separado e mostrar ao usuário uma página refrescada automaticamente que mostra o status, com uma barra de progresso ou outro visual sofisticado para mantê-los de estar entediado.

Veja Randal Schwartz's Assistindo processos longos através do CGI. O artigo usa Perl, mas a técnica não depende do idioma.

Pergunta muito semelhante aqui. Sugiro desova do processo longo e devolver uma barra de progresso baseada em Ajax ao usuário. Dessa forma, eles têm o luxo da interface da web e você tem o luxo de não ter intervalos.

O IMHO da melhor maneira seria executar um script independente que publica atualizações em algum lugar (arquivo plano, banco de dados, etc ...). Não sei como bifurcar um processo independente do Python, por isso não posso dar nenhum exemplo de código.

Para mostrar o progresso em um site, implemente uma solicitação AJAX para uma página que lê essas atualizações de status e, por exemplo, mostra uma boa barra de progresso.

Adicione algo como setTimeout ("RefreshProgressBar [...]) ou meta-refresch para refrescar automático.

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