优容网

女性化妆品分享网站,使用 Flask 构建 ...

↑我也要推荐

Flask 如何实现 auto reloader

发布时间:2013-08-18 22:48:56, 关注:+5578, 赞美:+4, 不爽:+4

原始出处: HX

简介

对于长时间执行的任务,我们不可能将其放在一个请求中完成,通常会用其他的方式异步执行。 队列则就是这样一个专门提供非阻塞任务执行的系统组件。在开发过程中我需要对其异步执行的任务进行测试,由于 Celery 没有提供Inprocess的API,所以不能直接在测试、开发的时候调用需要一番Tricky手段。由于Celery需要阻塞线程执行,无法直接作为后台任务,我们还需要在应用开始时,将其使用另外一个线程开启。

Flask Auto Reloader

Flask_ 的开发者模式(准确的来说是 WerkZeug_ 作为基础类库提供的)提供了许多工具,比如基于页面的Debuger提供网页版的Shell。但是开发模式会默认将auto_reloader开启,好处是不用在修改逻辑后手工重启,坏处是他不是直接启动WebServer,而是从子线程中执行WebServer后,主线程执行一个本地文件Watcher,在文件发生变动时重启。

下图为调试模式下执行逻辑

8c03b552-2832-40c9-9578-d05df9a92d92.jpe

CheckAndReloader过程中,一旦发现有.py[co]文件发生变更,则另外一个子进程,原进程退出。

为了复用逻辑,首次运行时不会直接执行 WebServer 部分,而是设置好环境变量WERKZEUG_RUN_MAIN后,进入 sMain 流程。下面为WerkZeugserving.py 部分代码:

def run_with_reloader(main_func, extra_files=None, interval=1):
    """Run the given function in an independent python interpreter."""
    import signal
    signal.signal(signal.SIGTERM, lambda *args: sys.exit(0))
    if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
        thread.start_new_thread(main_func, ())
        try:
            reloader_loop(extra_files, interval)
        except KeyboardInterrupt:
            return
    try:
        sys.exit(restart_with_reloader())
    except KeyboardInterrupt:
        pass

问题

麻烦在于,每一个在 Module 构建时创建对象,都会因为子进程的原因创建两次。

解决

不过既然知道了问题,我们屏蔽掉第一次执行母进程时的相关创建逻辑就行。
接下来问题就转换为如何判断当前进程是否为子进程的问题。 方法有很多,比如根据系统环境变量来WERKZEUG_RUN_MAIN来判断。或者比较父进程组ID,因为子进程所属于父进程组,所以可以根据如下方法判断。

# avoid Werbzeg's `run(use_reloader=True)` will create subprocess
if os.getppid() != os.getpgrp():
    __start_celelry_worker()

Conclusion

虽然解决了 Module 作用域下变量创建在 WerkZeug 调试模式中创建两次的问题,但是就问题本身来说解决的很不优美。
Flask 插件通常会绑定到 Flask.app 创建之后,通过一个工厂方法调用。项目中的例子不是标准的 Flask 插件,所以会发生这类问题。如果调试模式增加一个 Hook 用于*正常逻辑*的执行也能解决这个问题。究其原因毕竟时基于 Flask 应用模块生命周期问题,Flask 已经提供了一套严禁的API,按照它提供的思路执行就是。所谓逆我者亡,也只能怪自己只猜中这开头,猜不中这结局。

很多同学的 Sqlalchemy 和 Flask 结合的问题也通常卡在维护 Session 生命周期上。
选择一款框架绝对不是拿来主义,更多的是对原框架理念的一种赞同。

最后我还是考虑 Mock 掉这些API吧,哈哈。

References

如果你觉得本站对你有帮助,欢迎向本站赞助 :P

使用支付宝捐赠

Copyright© Python4cn(news, jobs) simple-is-better.com, 技术驱动:powered by web.py 空间主机:Webfaction

版权申明:文章转载已注明出处,如有疑问请来信咨询。本站为 python 语言推广公益网站,与 python 官方没有任何关系。

联系/投搞/留言: en.simple.is.better@gmail.com 向本站捐赠