debugging - asyncio.get_event_loop() 在 FLASK_DEBUG=1 时抛出错误

标签 debugging flask python-asyncio

我有一个紧跟 fast.ai 的渲染应用程序的 flask 应用程序:https://github.com/render-examples/fastai-v3 .它在页面呈现时使用 asyncio 下载模型。以下代码设置它:

loop = asyncio.get_event_loop()
tasks = [asyncio.ensure_future(setup_learner())] #setup_learner downloads the model
learn = loop.run_until_complete(asyncio.gather(*tasks))[0]
loop.close()

我注意到当 FLASK_DEBUG=1 时,第一行抛出错误:

RuntimeError: There is no current event loop in thread 'Thread-1'.



但是当 FLASK_DEBUG=0 时,它不会。但该应用程序更难调试。有没有人遇到过这个问题,是什么原因造成的?

最佳答案

这适用于 FLASK_DEBUG=0 的原因但不是 FLASK_DEBUG=1是因为该应用程序在未处于 Debug模式时在主线程中运行,但在处于 Debug模式时不在主线程中运行。

相关代码在 asyncio.events.BaseDefaultEventLoopPolicy.get_event_loop 中:

def get_event_loop():
    if (self._local._loop is None and
            not self._local._set_called and
            isinstance(threading.current_thread(), threading._MainThread)):
        self.set_event_loop(self.new_event_loop())

    if self._local._loop is None:
        raise RuntimeError('There is no current event loop in thread %r.'
                           % threading.current_thread().name)

    return self._local._loop

事件循环只能在具有当前事件循环策略的主线程中创建:_UnixDefaultEventLoopPolicy就我而言。请注意 _UnixDefaultEventLoopPolicy子类 BaseDefaultEventLoopPolicy但不会覆盖 BaseDefaultEventLoopPolicy .

可能的解决方案:
  • 在当前线程中创建一个新的事件循环 loop = asyncio.new_event_loop()
  • 创建允许 asyncio.get_event_loop() 的自定义事件循环策略通过覆盖 events.AbstractEventLoopPolicy.get_event_loop 在主线程以外的线程中创建新的事件循环方法。最安全的方法可能是子类化您的环境正在使用的任何事件循环策略并覆盖其 get_event_loop方法,去掉主线程检查。通过这种方式,您可以保留所有其他策略行为,但更改可能会破坏其中一些行为。

  • 无论哪种方式,您都在为线程创建事件循环。我的标准倾向是追求简单,所以#1。

    那么为什么在 Debug模式下应用程序不在主线程中运行?首先,在 Debug模式下运行时有两个进程:Flask 服务器和调试器,flask runpython pydevd.py , 分别。每个进程的主线程都有一个事件循环,用于促进应用服务器和调试器之间的通信——除其他外,并产生另一个实际运行应用的线程。如果应用程序由多线程应用程序服务器提供服务,您还将在未启用 Debug模式的情况下看到此行为,例如gunicorn 或 uwsgi。

    Flask 并不真正支持 asyncio .当然可以将它与 Flask 一起使用,但不能保证它们的兼容性。看到这个 issue ,更具体地说:the issue referenced in its comments

    关于debugging - asyncio.get_event_loop() 在 FLASK_DEBUG=1 时抛出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60406696/

    相关文章:

    python - 为什么查询 MySQL 数据库的 "user is taken"方法会传递不可变字典?

    python-3.x - 在Python3中异步删除文件的最佳方法?

    javascript - 通过Firebug分析DOM事件:hover

    python - 在 Flask 中显示来自 Base64 编码的 MongoDB 字段的图像

    angular - 可以从docker容器exec命令中访问URL,但是Angular应用获取ERR_CONNECTION_TIMED_OUT

    python - 带有 python Web 框架的 Websockets "quart"?

    python - 安装 asyncio 向后移植 trollius 时出现 gcc 错误(Python 2.7.5 和 Win7)

    debugging - 带延迟的 CSS3 旋转动画

    java - Eclipse 调试中的 IllegalStateException

    windows - Windows 上的 openocd 无效命令 "jtag",使用 olimex arm-usb-ocd-h jtag 加密狗,使用 phytec lpc3250 目标