J'ai écrit un script Python pour traiter certaines données des fichiers CSV. Le script prend entre 3 et 30 minutes à compléter, en fonction de la taille du CSV.
Maintenant, je souhaite mettre dans une interface Web à cela, je peux donc télécharger les fichiers de données CSV de n'importe où n'importe où. J'ai écrit une page de téléchargement de pots HTTP de base et utilisée le module CGI de Python - mais le script est juste après un certain temps. p>
Le script génère des en-têtes HTTP au début et génère des bits de données après itération sur chaque ligne du CSV. À titre d'exemple, cette instruction d'impression déclencherait toutes les 30 secondes environ. P>
[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
6 Réponses :
J'ai déjà eu cette situation et j'ai utilisé des cronjobs. Le script http écrirait simplement dans une file d'attente un travail à effectuer (un db ou un fichier dans un répertoire) et le cronjob le lirait et exécuterait ce travail. P>
+1; L'utilisateur pourrait être informé par courrier électronique lorsque son travail se termine, avec un lien pour le télécharger
Vous pouvez également faire de la cronjob Ecrire sa progression périodiquement dans un fichier et utiliser AJAX pour lire la valeur du serveur Web et l'afficher à l'utilisateur de son navigateur.
Si vous avez besoin du processus de travail pour exécuter en tant qu'utilisateur différent, l'utilisation d'un cronjob est certainement un bon moyen. D'autre, il est généralement aussi facile de démarrer le fil de traitement directement à partir de l'application CGI.
IMHO Le meilleur moyen serait d'exécuter un script indépendant qui publie des mises à jour quelque part (fichier plat, base de données, etc.). Je ne sais pas comment fourche un processus indépendant de Python, donc je ne peux pas donner d'exemples de code. P>
Pour montrer les progrès sur un site Web Implémentez une demande Ajax à une page qui lit ces mises à jour d'état et, par exemple, montre une belle barre de progression. P>
Ajouter quelque chose comme SettimeOut ("RefreshProgressBar [...]) ou méta-rafraîchir pour auto-rafraîchir. P>
Vous aurez probablement besoin de faire un Mais la manière appropriée de résoudre ce problème est que d'autres suggéraient de faire le traitement dans un thread / processus distinct et de montrer à l'utilisateur une page auto-rafraîchie qui affiche l'état, avec une barre de progression ou une autre fantaisie visuelle. les empêcher d'être ennuyé. p> stdout.flush () code>, car le script n'écrit pas vraiment rien au serveur Web jusqu'à ce que vous avez écrit une valeur de données de tampon de page - qui n'arrive pas avant le délai d'attente. p>
Ajouter des sys.stdout.flush () juste après une instruction d'impression dans la boucle semble résoudre le problème.
Je séparerais le travail comme celui-ci: p>
Une URL d'application Web qui accepte le fichier CSV publié. L'application Web met le contenu CSV dans une file d'attente hors ligne, par exemple une table de base de données. La réponse de l'application Web doit être une carte d'identité unique pour l'élément en file d'attente (utilisez une colonne d'identification automatique incrémentée, par exemple). Le client doit stocker cet identifiant pour la partie 3. P> li>
Une application de service autonome qui interroge la file d'attente de travail et le traitement. À la fin du traitement, stockez les résultats dans une autre table de base de données, à l'aide de l'ID unique en tant que clé. P> LI>
une URL d'application Web pouvant obtenir des résultats traités, http: // serveur / getResults / uniqueID / code>. Si le traitement est terminé (c'est-à-dire l'ID unique figurant dans la table de base de données des résultats), puis renvoyez les résultats. Si non terminé, la réponse doit être un code qui l'indique. Par exemple, une en-tête HTTP personnalisée, une réponse à l'état HTTP, un organisme de réponse "en attente" ou similaire. P> li>
ol>
Voir Randal Schwartz's Regarder les processus longs à travers CGI . L'article utilise Perl, mais la technique ne dépend pas de la langue. P>
Question très similaire Ici . Je suggère de reproduire le long processus et de renvoyer une barre de progression basée sur Ajax à l'utilisateur. De cette façon, ils utilisent le luxe de l'interface Web et vous avez le luxe de pas de temps. P>
Pensez-vous que quiconque est suffisamment patient pour attendre 30 minutes pour charger une page Web dans le navigateur, au lieu de télécharger des données?
Ceci est un script pour mon propre usage - j'ai normalement l'intention de l'utiliser sur mon ordinateur, mais je pensais qu'une interface Web pouvait être utile lors de voyages, ou par exemple à partir d'un téléphone. En outre, il n'y a vraiment rien à télécharger - le script sera envoyé par courrier électronique à un rapport à la fin.
@Pranab: "Ceci est un script pour mon propre usage." Alors quel problème avez-vous? Pourquoi ne pas simplement le laisser courir? Pourquoi gâcher? Si c'est pour vous - et cela n'envoie qu'un email - ce n'est même pas une page Web, n'est-ce pas? Pourquoi ne pas simplement écrire un script Python simple?
Je voulais une méthode de face Web accessible à partir d'un navigateur, mais le script tient dans le navigateur. Jusqu'à la réponse de Wim ci-dessous.
@Pranab: Je vais demander à nouveau. Pourquoi le Web face? Pourquoi navigateur? Si c'est pour votre propre usage, pourquoi ajouter cette complexité?
@ S.Lott: à utiliser via un téléphone, un ordinateur portable, de n'importe où - et tous les autres avantages clichés d'une «application Web» :-p comme éviter de configurer et de maintenir un script et des dépendances relativement complexes. Quant à la complexité supplémentaire - Eh bien, c'est une bonne occasion d'apprendre le design et de pratiquer Python :)
@Pranab: "Maintenir un script et des dépendances relativement complexes trois fois"? Vous ne pouvez pas simplement vous connecter à un serveur avec
PUTTY code> et exécutez-le simplement? Je pense que «simple» a plus d'avantages que «application Web» avec cette application spécifique. Ce n'est peut-être pas le meilleur problème pour pratiquer la conception de l'application Web avec.