【问题标题】:Flask/Werkzeug debugger, process model, and initialization codeFlask/Werkzeug 调试器、流程模型和初始化代码
【发布时间】:2012-07-19 06:37:33
【问题描述】:

我正在使用 Flask 编写 Python Web 应用程序。我的应用程序在启动时与另一台服务器建立连接,并在后台定期与该服务器通信。

如果我不使用 Flask 的内置调试器(使用 debug=False 调用 app.run),没问题。

如果我确实使用内置调试器(使用 debug=True 调用 app.run),Flask 会使用相同的代码启动第二个 Python 进程。最终侦听 HTTP 连接并通常按照我的应用程序应有的行为是子进程,我认为当调试器启动时父进程只是在那里监视它。

但是,这对我在两个进程中运行的启动代码造成了严重破坏;我最终与外部服务器建立了 2 个连接,2 个进程记录到同一个日志文件,并且通常它们会相互绊倒。

我认为在调用 app.run() 之前我不应该做真正的工作,但是我应该把这个初始化代码放在哪里(我只想每个 Flask 进程组运行一次​​,无论调试器模式如何,但是哪个需要在启动时运行并且独立于客户端请求)?

我发现this question about "Flask auto-reload and long-running thread" 这有点相关,但有些不同,答案对我没有帮助。 (我也有一个单独的长时间运行的线程标记为守护线程,但是当重新加载器启动时它会被杀死,但我要解决的问题是在任何重新加载需要发生之前。我不关心重新加载;我关心的是额外的进程,以及避免在父进程中执行不必要代码的正确方法。)

【问题讨论】:

  • 感谢这个问题(和回答),这个问题让我在尝试类似的事情时感到困惑。

标签: python flask wsgi werkzeug


【解决方案1】:

我确认这种行为是由于 Werkzeug 而不是 Flask 本身,它与重新加载器有关。你可以在 Werkzeug 的 serving.py 中看到这一点——在 run_simple() 中,如果 use_reloader 为真,它会通过一个辅助函数 run_with_reloader() / restart_with_reloader() 调用 make_server,它会在设置一个 subprocess.call(sys.executable) 之后环境变量 WERKZEUG_RUN_MAIN 将被子进程继承。

我用一个相当丑陋的 hack 解决了这个问题:在我的主函数中,在创建 wsgi 应用程序对象并调用 app.run() 之前,我寻找 WERKZEUG_RUN_MAIN:

if use_reloader and not os.environ.get('WERKZEUG_RUN_MAIN'):
    logger.warning('startup: pid %d is the werkzeug reloader' % os.getpid())
else:
    logger.warning('startup: pid %d is the active werkzeug' % os.getpid()
    # my real init code is invoked from here

如果在 Werkzeug 开始提供服务之前调用了一个方法,我觉得最好从应用程序对象内部完成。不过我不知道有这种方法。

这一切都归结为:在 Werkzeug 的 run_simple.py 中,最终只会调用一次 make_server().serve_forever(),但可能会调用两次 run_simple()(整个调用堆栈最多那一点)在我们进入 make_server() 之前。

【讨论】:

  • 我认为这个答案可能已经过时了。 Flask 现在有一个 before_first_request 装饰器。
猜你喜欢
  • 2021-06-22
  • 2011-05-11
  • 2013-06-19
  • 2011-07-26
  • 2012-02-27
  • 2012-08-17
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多