Wie richte ich das automatische Laden mit Flask + uWSGI ein?
Frage
Ich suche nach etwas wie uWSGI + Django-Autoreload-Modus für Flask.
Lösung
Sie können versuchen, Supervisord als Manager für Ihre Uwsgi-App zu verwenden.Es hat auch eine Überwachungsfunktion, die einen Prozess automatisch neu lädt, wenn eine Datei oder ein Ordner "berührt" / geändert wurde.
Hier finden Sie ein nettes Tutorial: Flasche+ NginX + Uwsgi + Supervisord
Andere Tipps
Ich verwende uwsgi Version 1.9.5 und die Option
uwsgi --py-autoreload 1
funktioniert hervorragend
Wenn Sie uwsgi
mit Befehlsargumenten konfigurieren, übergeben Sie --py-autoreload=1
:
uwsgi --py-autoreload=1
Wenn Sie eine .ini
-Datei zum Konfigurieren von uwsgi
und uwsgi --ini
verwenden, fügen Sie Ihrer .ini
-Datei Folgendes hinzu:
py-autoreload = 1
Für Entwicklungsumgebungen können Sie versuchen, zu verwenden --python-autoreload uwsgis Parameter. Wenn Sie sich den Quellcode ansehen, funktioniert er möglicherweise nur im Thread-Modus (--enable-threads).
Die Funktion zum automatischen Neuladen von Flask im Entwicklungsmodus wird tatsächlich von der zugrunde liegenden Werkzeug-Bibliothek bereitgestellt. Der relevante Code ist in werkzeug/serving.py
- es lohnt sich, einen Blick darauf zu werfen. Grundsätzlich erzeugt die Hauptanwendung den WSGI-Server als einen Unterprozess, der jede aktive .py
-Datei einmal pro Sekunde auf der Suche nach Änderungen bewertet. Wenn etwas angezeigt wird, wird der Unterprozess beendet und der übergeordnete Prozess startet ihn erneut - und lädt die Chages neu.
Es gibt keinen Grund, warum Sie eine ähnliche Technik auf der Ebene von uWSGI nicht implementieren könnten. Wenn Sie keine stat-Schleife verwenden möchten, können Sie versuchen, die zugrunde liegenden Befehle zur Überwachung von Betriebssystemdateien zu verwenden. Anscheinend (gemäß Werkzeugs Code) ist pyinotify fehlerhaft, aber vielleicht Watchdog funktioniert? Probieren Sie ein paar Dinge aus und sehen Sie, was passiert.
Bearbeiten:
Als Antwort auf den Kommentar denke ich, dass dies ziemlich einfach zu implementieren wäre. Aufbauend auf dem Beispiel aus Ihrem Link zusammen mit dem Code von werkzeug/serving.py
:
""" NOTE: _iter_module_files() and check_for_modifications() are both
copied from Werkzeug code. Include appropriate attribution if
actually used in a project. """
import uwsgi
from uwsgidecorators import timer
import sys
import os
def _iter_module_files():
for module in sys.modules.values():
filename = getattr(module, '__file__', None)
if filename:
old = None
while not os.path.isfile(filename):
old = filename
filename = os.path.dirname(filename)
if filename == old:
break
else:
if filename[-4:] in ('.pyc', '.pyo'):
filename = filename[:-1]
yield filename
@timer(3)
def check_for_modifications():
# Function-static variable... you could make this global, or whatever
mtimes = check_for_modifications.mtimes
for filename in _iter_module_files():
try:
mtime = os.stat(filename).st_mtime
except OSError:
continue
old_time = mtimes.get(filename)
if old_time is None:
mtimes[filename] = mtime
continue
elif mtime > old_time:
uwsgi.reload()
return
check_for_modifications.mtimes = {} # init static
Es ist ungetestet, sollte aber funktionieren.
import gevent.wsgi
import werkzeug.serving
@werkzeug.serving.run_with_reloader
def runServer():
gevent.wsgi.WSGIServer(('', 5000), app).serve_forever()
(Sie können einen beliebigen WSGI-Server verwenden)
Ich befürchte, dass Flask wirklich zu bloß ist, um eine Implementierung wie diese standardmäßig zu bündeln.
Das dynamische Neuladen von Code in der Produktion ist im Allgemeinen eine schlechte Sache. Wenn Sie sich jedoch Sorgen über eine Entwicklungsumgebung machen, schauen Sie sich dieses Bash-Shell-Skript an. http://aplawrence.com/Unixart/watchdir.html
Ändern Sie einfach das Schlafintervall nach Ihren Wünschen und ersetzen Sie den Befehl echo durch den Befehl, mit dem Sie uwsgi neu laden.Ich führe den uwsgi un master-Modus aus und sende einfach einen killall uwsgi-Befehl.