Ich schreibe eine Python-Webanwendung mit Flask. Meine Anwendung stellt beim Start eine Verbindung zu einem anderen Server her und kommuniziert periodisch mit diesem Server im Hintergrund.
Wenn ich Flasks eingebauten Debugger nicht benutze (app.run mit debug = False aufrufen), kein Problem.
Wenn ich den eingebauten Debugger benutze (Aufruf von app.run mit debug = True), startet Flask einen zweiten Python-Prozess mit demselben Code. Es ist der Kindprozess, der nach HTTP-Verbindungen horcht und sich im Allgemeinen so verhält, wie meine Anwendung es beabsichtigt, und ich vermute, dass der Elternteil nur da ist, um darauf zu wachen, wenn der Debugger einsetzt.
Das verursacht jedoch Chaos mit meinem Startcode, der in beiden Prozessen ausgeführt wird; Ich habe am Ende 2 Verbindungen mit dem externen Server, 2 Prozesse protokollieren in der gleichen Logdatei, und in der Regel stolpern sie über einander.
Ich nehme an, dass ich vor dem Aufruf von app.run () keine echte Arbeit machen sollte, aber wo sollte ich diesen Initialisierungscode setzen (den ich nur einmal pro Flask-Prozessgruppe ausführen möchte, unabhängig vom Debugger-Modus, aber welche muss beim Start und unabhängig von Client-Anfragen laufen)?
Ich fand diese Frage zu "Flask auto-reload und lang laufenden Thread " das ist etwas verwandt, aber etwas anders, und die Antwort hat mir nicht geholfen. (Ich habe auch einen separaten, lang laufenden Thread, der als Daemon-Thread markiert ist, aber er wird beendet, wenn der Reloader startet, aber das Problem, das ich lösen will, ist, bevor ein Reload stattfinden muss neu laden; ich bin besorgt über den zusätzlichen Prozess und den richtigen Weg, um unnötigen Code im übergeordneten Prozess zu vermeiden.)
Ich habe bestätigt, dass dieses Verhalten auf Werkzeug und nicht auf Flask zurückzuführen ist und dass es mit dem Reloader zusammenhängt. Sie können dies in Werkzeug serving.py - in run_simple () sehen, wenn use_loader wahr ist, ruft es make_server über eine Hilfsfunktion run_with_loader () / restart_with_loader () auf, die eine subprocess.call (sys.executable) ausführt, nachdem ein gesetzt wurde Umgebungsvariable WERKZEUG_RUN_MAIN in der Umgebung, die vom Subprozess übernommen wird.
Ich habe mit einem ziemlich hässlichen Hack herumgearbeitet: In meiner Hauptfunktion suche ich vor dem Erstellen des wsgi-Anwendungsobjekts und dem Aufruf von app.run () nach WERKZEUG_RUN_MAIN:
%Vor%Ich habe das Gefühl, dass dies besser aus dem Anwendungsobjekt heraus geschehen würde, wenn es eine Methode gibt, die aufgerufen wird, bevor Werkzeug es zu bedienen beginnt. Ich kenne diese Methode allerdings nicht.
Das alles läuft darauf hinaus: In Werkzeug run_simple.py gibt es nur einen eventuellen Aufruf von make_server (). serve_forever (), aber es gibt möglicherweise zwei Aufrufe von run_simple () (und den gesamten Call-Stack bis zu diesen Punkt), bevor wir es zu make_server () machen.