如何使用Flask + uWSGI设置自动重装?

How to set up autoreload with Flask+uWSGI?

我正在寻找Flask的uWSGI + Django自动重载模式。


我正在运行uwsgi 1.9.5版本和该选项

1
uwsgi --py-autoreload 1

效果很好


如果要使用命令参数配置uwsgi,请传递--py-autoreload=1

1
uwsgi --py-autoreload=1

如果使用.ini文件配置uwsgi并使用uwsgi --ini,则将以下内容添加到.ini文件中:

1
py-autoreload = 1

对于开发环境,您可以尝试使用
--python-autoreload uwsgi的参数。
查看源代码,它可能仅在线程模式(--enable-threads)下工作。


您可以尝试使用超级用户作为Uwsgi应用程序的管理员。它还具有监视功能,当"触摸" /修改了文件或文件夹时,该功能会自动重新加载进程。

您将在此处找到一个不错的教程:Flask + NginX + Uwsgi + Supervisord


开发模式Flask的自动重载功能实际上是由基础的Werkzeug库提供的。相关代码在werkzeug/serving.py中-值得一看。但基本上,主应用程序将WSGI服务器作为子进程生成,该子进程每秒统计一次每个活动的.py文件,以查找更改。如果看到任何内容,子进程将退出,父进程将再次启动它进行备份-实际上是重新加载了更改。

没有理由不能在uWSGI层上实现类似的技术。如果您不想使用stat循环,则可以尝试使用基础OS文件监视命令。显然(根据Werkzeug的代码),pyinotify是越野车,但也许Watchdog可以工作?尝试一些事情,看看会发生什么。

编辑:

作为回应,我认为这很容易重新实现。以链接提供的示例以及werkzeug/serving.py中的代码为基础:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
""" 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

它未经测试,但应该可以工作。


1
2
3
4
5
6
import gevent.wsgi
import werkzeug.serving

@werkzeug.serving.run_with_reloader
def runServer():
    gevent.wsgi.WSGIServer(('', 5000), app).serve_forever()

(您可以使用任意WSGI服务器)


恐怕Flask实在是太空洞了,因此默认情况下捆绑了这样的实现。

在生产环境中动态重载代码通常是一件坏事,但是如果您担心开发环境,请查看以下bash shell脚本http://aplawrence.com/Unixart/watchdir.html

只需将睡眠间隔更改为适合您需要的时间,然后将echo命令替换为您用来重新加载uwsgi的任何内容即可。我运行uwsgi un master模式,然后发送killall uwsgi命令。