Django: Soll ich einen separaten Prozess starten?

8

Ich schreibe eine App, mit der der Benutzer Daten in eine Datei hochladen kann; Die App wird diese Daten verarbeiten und die Ergebnisse per E-Mail an den Benutzer senden. Die Verarbeitung kann einige Zeit in Anspruch nehmen, daher möchte ich dies separat in einem Python-Skript behandeln, anstatt in der Ansicht darauf zu warten, dass sie abgeschlossen wird. Das Python-Skript und die Python-Ansicht müssen nicht kommunizieren, da das Skript die Daten aus einer Datei aufnimmt, die von der Ansicht geschrieben wurde. Die Ansicht wird nur eine Nachricht wie "Vielen Dank für das Hochladen Ihrer Daten - die Ergebnisse werden Ihnen per E-Mail gesendet werden"

Was ist der beste Weg, dies in Django zu tun? Einen separaten Prozess erzeugen? Etwas in eine Warteschlange stellen?

Ein Beispielcode würde sehr geschätzt werden. Danke.

    
FunLovinCoder 27.11.2010, 13:36
quelle

4 Antworten

17

Die einfachste mögliche Lösung besteht darin, benutzerdefinierte Befehle zu schreiben, die nach allen suchen die nicht verarbeiteten Dateien, verarbeitet sie und sendet dann eine E-Mail an den Benutzer. Die Verwaltungsbefehle laufen innerhalb des Django-Frameworks, so dass sie Zugriff auf alle Modelle, Datenbankverbindungen usw. haben, aber Sie können sie von überall aufrufen, zum Beispiel crontab.

Wenn Sie sich über den Zeitraum zwischen dem Hochladen der Datei und dem Start der Verarbeitung Gedanken machen, können Sie ein Framework wie Sellerie verwenden Hilfsbibliothek für die Verwendung einer Nachrichtenwarteschlange und Ausführen von Arbeitern, die die Warteschlange überwachen. Dies wäre eine ziemlich niedrige Latenz, aber auf der anderen Seite könnte Einfachheit für Sie wichtiger sein.

Ich rate dringend davon ab, Threads oder Launch-Prozesse in Ihren Ansichten zu starten, da die Threads innerhalb des django-Prozesses laufen und Ihren Webserver (abhängig von Ihrer Konfiguration) zerstören könnten. Der untergeordnete Prozess erbt alles vom Django-Prozess, den Sie wahrscheinlich nicht möchten. Es ist besser, dieses Zeug getrennt zu halten.

    
knutin 27.11.2010, 14:29
quelle
4

Ich habe derzeit ein Projekt mit ähnlichen Anforderungen (nur komplizierter ^^).

Erzeuge niemals einen Subprozess oder einen Thread aus deiner Django-Ansicht. Du hast keine Kontrolle über die Django-Prozesse und es könnte vor dem Ende der Aufgabe getötet, pausiert usw. werden. Es wird vom Webserver gesteuert (z. B. Apache über WSGI).

Was ich tun würde, wäre ein externes Skript, das in einem separaten Prozess laufen würde. Sie haben zwei Lösungen, die ich denke:

  • Ein Prozess, der immer das Verzeichnis ausführt und durchsucht, in dem Sie Ihre Dateien abgelegt haben. Es würde zum Beispiel das Verzeichnis alle zehn Sekunden überprüfen und die Dateien
  • verarbeiten
  • Wie oben, aber alle x Sekunden nach cron. Dies hat im Grunde die gleiche Wirkung
  • Verwenden Sie Sellerie zum Erstellen von Arbeitsprozessen und zum Hinzufügen von Jobs zur Warteschlange mit Ihrer Django-Anwendung. Dann müssen Sie die Ergebnisse mit einem der Mittel, die mit Sellerie erhältlich sind, zurückbekommen.

Nun müssen Sie wahrscheinlich auf die Informationen in Django-Modellen zugreifen, um den Benutzer am Ende per E-Mail zu erreichen. Hier haben Sie mehrere Lösungen:

  • Importieren Sie Ihre Module (Modelle usw.) aus dem externen Skript
  • Implementieren Sie das externe Skript als benutzerdefinierten Befehl (wie vorgeschlagen)
  • Kommunizieren Sie die Ergebnisse beispielsweise über eine POST-Anfrage an die Django-Anwendung. Dann würden Sie die E-Mail senden und Statusänderungen usw. in einer normalen Django-Ansicht machen.

Ich würde für einen externen Prozess gehen und die Module oder POST-Anfrage importieren. Auf diese Weise ist es viel flexibler. Sie könnten zum Beispiel das Multiprocessing-Modul verwenden, um mehrere Dateien gleichzeitig zu verarbeiten (und so effizient Multicore-Maschinen zu verwenden).

Ein einfacher Workflow wäre:

  1. Überprüfen Sie das Verzeichnis auf neue Dateien
  2. Für jede Datei (kann parallelisiert werden):
    1. Prozess
    2. Senden Sie eine E-Mail oder benachrichtigen Sie Ihre Django-Anwendung
  3. Schlafe eine Weile

Mein Projekt enthält eine wirklich CPU-intensive Verarbeitung. Ich verwende derzeit einen externen Prozess, der einem Pool von Worker-Prozessen Verarbeitungsjobs gibt (das ist im Grunde das, was Sellery für Sie tun kann) und meldet den Fortschritt und die Ergebnisse über POST-Anfragen an die Django-Anwendung zurück. Es funktioniert wirklich gut und ist relativ skalierbar, aber ich werde es bald ändern, um Sellerie auf einem Cluster zu verwenden.

    
Marc Demierre 27.11.2010 15:05
quelle
3

Sie könnten einen Thread erstellen, um die Verarbeitung durchzuführen. Es hätte nicht viel mit Django zu tun; Die View-Funktion müsste den Worker-Thread starten und das war's.

Wenn Sie wirklich einen separaten Prozess wünschen, benötigen Sie das Modul Unterprozess . Aber müssen Sie die Standard-E / A wirklich umleiten oder eine externe Prozesssteuerung zulassen?

Beispiel:

%Vor%

Ich habe kein Programm erstellt, bei dem ich den Fortschritt der Threads nicht verfolgen wollte, also weiß ich nicht, ob das funktioniert, ohne das Thread -Objekt irgendwo zu speichern. Wenn Sie das tun müssen, ist es ziemlich einfach:

%Vor%

Sie können Threads aus der Liste entfernen, wenn thread.is_alive() False zurückgibt:

%Vor%     
Mike DeSimone 27.11.2010 13:58
quelle
1

Sie könnten Multiprocessing verwenden. Ссылка

Im Wesentlichen

%Vor%     
Skylar Saveland 12.01.2011 05:34
quelle

Tags und Links