Question

J'ai écrit un script python pour traiter des données à partir de fichiers CSV. Le script prend entre 3 à 30 minutes pour remplir, en fonction de la taille du CSV.

Maintenant, je veux mettre dans une interface Web pour cela, donc je peux télécharger les fichiers de données CSV partout. J'ai écrit une page de téléchargement HTTP POST de base et utilisé le module CGI Python - mais le script juste après un certain temps sur le temps.

Le script affiche les en-têtes HTTP au début et sorties bits de données après itérer sur chaque ligne du CSV. À titre d'exemple, cette déclaration d'impression déclencherait toutes les 30 secondes.

# 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 />"

Je supposais le navigateur recevrait les en-têtes, et attendre, car il continue de recevoir des petits bits de données. Mais ce qui semble réellement se produire est-il ne reçoit pas de données du tout, et les temps de Error 504 quand donné un fichier CSV avec beaucoup de lignes.

Peut-être il y a une mise en cache qui se passe quelque part? À partir des journaux,

[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

Quelle est la meilleure façon de résoudre ce problème, ou est-il pas approprié d'exécuter ces scripts dans un navigateur?

Edit: Ceci est un script pour mon propre usage - Je compte normalement l'utiliser sur mon ordinateur, mais je pensais que d'une interface basée sur le Web pourrait être utile lors d'un voyage, ou par exemple à partir d'un téléphone. En outre, il n'y a vraiment rien à télécharger -. Le script très probablement e-mail un rapport de fin

Était-ce utile?

La solution

Je séparerais le travail comme ceci:

  1. Une URL application web qui accepte le fichier CSV ci-dessous. L'application web met le contenu CSV dans une file d'attente de ligne de hors tension, par exemple une table de base de données. La réponse de l'application Web doit être un ID unique de l'élément mis en attente (utiliser une colonne ID auto-incrémentée, par exemple). Le client doit conserver cet ID pour une partie 3.

  2. Une application de service autonome qui interroge la file d'attente pour le travail, et fait le traitement. À la fin du traitement, stocker les résultats dans une autre table de base de données, en utilisant l'identifiant unique comme clé.

  3. Une URL de l'application Web qui peut obtenir des résultats transformés, http://server/getresults/uniqueid/. Si le traitement est terminé (à savoir l'ID unique se trouve dans la table de base de données de résultats), puis retourner les résultats. Sinon terminé, la réponse doit être un code qui indique. Par exemple, un en-tête HTTP personnalisé, une réponse d'état HTTP, le corps de réponse 'pending' ou similaire.

Autres conseils

J'ai eu cette situation avant et je cronjobs. Le script HTTP serait tout simplement écrire dans une file d'attente d'un travail à effectuer (un DB ou un fichier dans un répertoire) et le cronjob lirait et exécuter cette tâche.

Vous aurez probablement besoin de faire un stdout.flush(), que le script n'écrit pas vraiment quoi que ce soit encore le serveur Web jusqu'à ce que vous avez écrit la valeur d'un tampon de page de données -. Qui ne se produit pas avant que le délai d'attente

Mais la bonne façon de résoudre ce problème est, comme d'autres ont suggéré, pour effectuer le traitement dans un thread / processus séparé, et montrer à l'utilisateur une page rafraîchie automatique qui indique l'état, avec une barre de progression ou d'une autre fantaisie visuelle pour les empêcher de s'ennuyer.

Voir Randal Schwartz Regarder un long processus par CGI . L'article utilise Perl, mais la technique ne dépend pas de la langue.

question très similaire . Je suggère fraie au large du processus long et le retour d'une barre de progression en fonction ajax à l'utilisateur. De cette façon, ils utilisateur a le luxe de l'interface web et vous avez le luxe de pas temporisations.

AMHA la meilleure façon serait d'exécuter un script indépendant qui affiche les mises à jour quelque part (fichier plat, base de données, etc ...). Je ne sais pas comment fork un processus indépendant de python, donc je ne peux pas donner des exemples de code.

Pour réaliser des progrès sur un WebSite mettre en œuvre une demande ajax à une page qui lit les mises à jour de statut et montre par exemple une barre de progression agréable.

Ajouter quelque chose comme setTimeout ( "refreshProgressBar [...]) ou méta-refresh pour l'auto-rafraîchissement.

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