Erstellen einer Webschnittstelle für ein Skript, das 30 Minuten zur Ausführung benötigt

7

Ich habe ein Python-Skript geschrieben, um einige Daten aus CSV-Dateien zu verarbeiten. Das Skript dauert zwischen 3 und 30 Minuten, abhängig von der Größe der CSV.

Jetzt möchte ich ein Webinterface einfügen, damit ich die CSV-Dateien von überall hochladen kann. Ich schrieb eine grundlegende HTTP-POST-Upload-Seite und benutzte Pythons CGI-Modul - aber das Skript kommt nach einiger Zeit einfach mal aus.

Das Skript gibt am Anfang HTTP-Header aus und gibt Datenbits aus, nachdem es über jede Zeile der CSV-Datei iteriert wurde. Als Beispiel würde diese Druckanweisung alle 30 Sekunden oder so ausgelöst.

%Vor%

Ich ging davon aus, dass der Browser die Header erhalten würde und warte, da er weiterhin kleine Datenmengen empfängt. Aber was tatsächlich zu passieren scheint, ist, dass es überhaupt keine Daten erhält, und Error 504 läuft ab, wenn man eine CSV mit vielen Zeilen erhält.

Vielleicht passiert irgendwo irgendwo Caching? Aus den Protokollen,

%Vor%

Was ist der beste Weg, dies zu lösen, oder ist es nicht angemessen, solche Skripte in einem Browser auszuführen?

Bearbeiten: Dies ist ein Skript für meinen eigenen Gebrauch - ich beabsichtige normalerweise, es auf meinem Computer zu verwenden, aber ich dachte, dass eine Web-basierte Schnittstelle könnte nützlich sein, während der Reise oder zum Beispiel von einem Telefon. Außerdem gibt es wirklich nichts herunterzuladen - das Skript wird am Ende wahrscheinlich einen Bericht per E-Mail versenden.

    
Pranab 20.01.2010, 11:47
quelle

6 Antworten

12

Ich würde die Arbeit so trennen:

  1. Eine Web-App-URL, die die POST-CSV-Datei akzeptiert. Die Web-App platziert den CSV-Inhalt in eine Offline-Warteschlange, beispielsweise eine Datenbanktabelle. Die Antwort der Web-App sollte eine eindeutige ID für das in der Warteschlange befindliche Element sein (z. B. eine automatisch inkrementierte ID-Spalte). Der Client muss diese ID für Teil 3 speichern.

  2. Eine eigenständige Dienstanwendung, die die Warteschlange nach Arbeit abruft und die Verarbeitung durchführt. Speichern Sie die Ergebnisse nach Abschluss der Verarbeitung in einer anderen Datenbanktabelle, wobei Sie die eindeutige ID als Schlüssel verwenden.

  3. Eine Web-App-URL, die Ergebnisse verarbeiten kann, http://server/getresults/uniqueid/ . Wenn die Verarbeitung beendet ist (d. H. Die eindeutige ID ist in der Ergebnisdatenbanktabelle gefunden), geben Sie die Ergebnisse zurück. Wenn nicht abgeschlossen, sollte die Antwort ein Code sein, der dies anzeigt. Zum Beispiel ein benutzerdefinierter HTTP-Header, eine HTTP-Statusantwort, Antworttext 'PENDING' oder ähnliches.

codeape 20.01.2010, 12:00
quelle
5

Ich hatte diese Situation schon vorher und habe Cronjobs benutzt. Das HTTP-Skript würde einfach in eine Warteschlange einen auszuführenden Job schreiben (eine DB oder eine Datei in einem Verzeichnis) und der Cronjob würde es lesen und diesen Job ausführen.

    
sharjeel 20.01.2010 11:52
quelle
4

Sie müssen wahrscheinlich stdout.flush() eingeben, da das Skript noch nichts auf den Webserver schreibt, bis Sie die Daten eines Seitenpuffers geschrieben haben - was nicht vor dem Timeout geschieht.

Aber der richtige Weg, um dies zu lösen, ist, wie andere vorgeschlagen haben, die Verarbeitung in einem separaten Thread / Prozess zu machen und dem Benutzer eine automatisch aufgefrischte Seite zu zeigen, die den Status mit einem Fortschrittsbalken oder einem anderen visuellen Bild zeigt um sie davon abzuhalten gelangweilt zu werden.

    
Wim 20.01.2010 11:59
quelle
2

Siehe Randal Schwartz Lange Prozesse durch CGI beobachten . Der Artikel verwendet Perl, aber die Technik hängt nicht von der Sprache ab.

    
Sinan Ünür 20.01.2010 12:03
quelle
2

Sehr ähnliche Frage hier . Ich schlage vor, den langwierigen Prozess zu starten und dem Benutzer einen Ajax-basierten Fortschrittsbalken zurückzugeben. So haben sie den Luxus des Web-Interface und Sie haben den Luxus, keine Auszeiten zu haben.

    
whatnick 20.01.2010 12:06
quelle
1

imho der beste Weg wäre, ein unabhängiges Skript, das Updates irgendwo (flache Datei, Datenbank, etc ...) veröffentlicht. Ich weiß nicht, wie man einen unabhängigen Prozess von python ausbildet, also kann ich keine Code-Beispiele geben.

Um den Fortschritt auf einer WebSite anzuzeigen, implementieren Sie eine AJAX-Anfrage an eine Seite, die diese Statusaktualisierungen liest und zum Beispiel eine nette Fortschrittsleiste anzeigt.

Fügen Sie etwas wie setTimeout ("refreshProgressBar [...]) oder Meta-Refresh für die automatische Aktualisierung hinzu.

    
dbemerlin 20.01.2010 11:54
quelle