如何使用 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 来工作。谢谢!
我认为值得注意的是,1
和 true
的值在这里不可互换。只有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 设置自动重载?的主要内容,如果未能解决你的问题,请参考以下文章
如何通过gevent使用Flask(uWSGI 和Gunicorn 版本)
我应该为 Flask、uWSGI 和 nginx 提供单独的容器吗?