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

Posted

技术标签:

【中文标题】如何使用 Flask+uWSGI 设置自动重载?【英文标题】:How to set up autoreload with Flask+uWSGI? 【发布时间】:2012-02-08 13:05:23 【问题描述】:

我正在为 Flask 寻找类似 @​​987654321@ 的东西。

【问题讨论】:

【参考方案1】:

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

uwsgi --py-autoreload 1

效果很好

【讨论】:

使用 uwsgi Emperor 模式,既不适用于 Emperor 进程启动,也不适用于单独的应用程序 ini 配置。前者给出“未知选项”,后者给出什么。无论哪种方式,都必须重新启动流程才能注意到更改... 如何运行 uwsgi --py-autoreload 1 realpath() of --py-autoreload=1 failed: No such file or directory [core/utils.c line 3651]【参考方案2】:

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

uwsgi --py-autoreload=1

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

py-autoreload = 1

【讨论】:

【参考方案3】:

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

【讨论】:

这个对我有用。将python-autoreload = 1 添加到我的uwsgi.ini 文件可以重新加载它!谢谢! 使用 uwsgi Emperor 模式 - 这通过添加到应用程序的 ini 来工作。谢谢! 我认为值得注意的是,1true 的值在这里不可互换。只有1 适合我。 @kungphu 再次阅读了文档,它说启用后它会启动一个线程来扫描更改。您设置的值是它进行扫描的时间间隔。 @AdamRitter 我不小心将 sn-p 链接了两次。 sn-p 表示py-autoreload;文档没有。此外,这不是被询问的属性,即python-autoreload。有 several options in the actual doc 似乎是相同的,包括这两个,尽管它们没有标记为别名。这有点令人困惑,无论如何,关于该行为的描述都不清楚。如果我知道实际发生了什么,我会向文档提交一个补丁。【参考方案4】:

您可以尝试使用 supervisord 作为您的 Uwsgi 应用程序的管理器。它还具有监视功能,可在文件或文件夹被“触摸”/修改时自动重新加载进程。

你会在这里找到一个很好的教程:Flask+nginx+Uwsgi+Supervisord

【讨论】:

链接已失效 存档:web.archive.org/web/20120924045956/http://www.readncode.com:80/… 可疑链接?【参考方案5】:

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

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

编辑:

作为对评论的回应,我认为这很容易重新实现。基于您的链接提供的示例以及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

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

【讨论】:

感谢您的提示!我通过 werkzeug.serving 看了一点,但希望我可以避免弄脏我的手,通过要求一个快速的解决方案......也许是时候有人实施它了。 :)【参考方案6】:
import gevent.wsgi
import werkzeug.serving

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

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

【讨论】:

不幸的是,这不是我的问题的答案。我希望 uwsgi 提供服务。顺便说一句:Flask 的 app.run(debug=True) 提供开箱即用的重新加载。 虽然开发。 Flask 附带的 webserver 提供了重新加载,它还提供了一个用于调试的 shell!你不想给生产中的每个人一个 python shell!【参考方案7】:

恐怕 Flask 实在是太简单了,无法默认捆绑这样的实现。

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

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

【讨论】:

以上是关于如何使用 Flask+uWSGI 设置自动重载?的主要内容,如果未能解决你的问题,请参考以下文章

flask使用工厂函数后怎么用uwsgi启动?

如何通过gevent使用Flask(uWSGI 和Gunicorn 版本)

我应该为 Flask、uWSGI 和 nginx 提供单独的容器吗?

flask项目下的uwsgi配置方式及示例

centos部署flask+nginx+uwsgi之踩坑指南

nginx+uwsgi+flask搭建后怎么访问.py文件