RuntimeError: You cannot use AsyncToSync in the same thread as an async event loop

RuntimeError: You cannot use AsyncToSync in the same thread as an async event loop

我正在使用 Flask 在 python 中制作仪表板。 它需要 运行 三个任务:flask、datastream_handler()dashboard_handler()。其中一项任务 datastream_handler() 必须是异步函数。

我使用线程允许任务同时运行,(flask和dashboard_handler()是线程,datastream_handler()是来自主线程的运行线程)。

dashboard_handler()datastream_handler() 启动,运行 完美启动,flask 似乎启动了,但是当我访问该网页时,它在终端中给我一个错误: RuntimeError: You cannot use AsyncToSync in the same thread as an async event loop - just await the async function directly.

我很困惑,因为我直接等待了异步函数(datastream_handler)?

我试过切换它,使 flask 成为主线程,datastream_handler() 作为 threading.Thread 启动(使用 asyncio.run 从非线程启动异步函数-异步功能)。然而,这只是给出了同样的错误。

我查了一下这个错误,有几个人在使用 Django 和 requests-html 时遇到了同样的错误-html,但是他们的发现是针对他们各自的框架的,不能应用于 flask。

这是我的代码:

datastream_handlerdashboard_handler 在不同的文件中; dashboard_handler 只是一个带 while 循环的普通同步函数,而 datastream_handler 是一个异步函数,目前仅包含一个带有 print 和 asyncio.sleep 的 while 循环,用于测试目的。

我不认为这些函数的内容导致了错误,但如果我错了请纠正我

app = Flask(__name__)
socket = SocketIO(app)

@app.route("/")
async def index():
    return render_template("index.html")

def start_flask():
    socket.run(app, host="0.0.0.0", port=5000)
        
async def main():

    q = Queue() #queue for data transfer
    threading.Thread(target=dashboard_handler, args=(q,), daemon=True).start()
    threading.Thread(target=start_flask, daemon=True).start()

    await datastream_handler(q)


if __name__ == "__main__":
    asyncio.run(main())

如果有人能帮助我,我将不胜感激

谢谢

Flask放在线程中的原因是什么? Flask应用应该在主线程中启动。

关于这个错误, RuntimeError: You cannot use AsyncToSync in the same thread as an async event loop - just await the async function directly.

我认为这有两个原因:

  1. 您运行在线程中使用 Flask
  2. 您正在使用 async def index() 烧瓶将使用 asgiref 的模块 AsyncToSync 将其转换为线程异步,并且无法在线程中完成。

如果你想 运行 3 个并发使用线程,其中一个是 asynchronous 也许你可以使用 python-worker link

  1. datastream_handlerdashboard_handler 定义为工人
from worker import worker, async_worker

@async_worker
async def datastream_handler(q):
    ...

@worker
def dashboard_handler(q):
    ...
  1. 在你的主文件中:
if __name__ == "__main__":
    q = Queue()
    asyncio.run(datastream_handler(q))
    dashboard_handler(q)
    socket.run(app, host="0.0.0.0", port=5000)

datastream_handlerdashboard_handler 将自动 运行 作为一个线程。