Asyncio 与另一个协程同时运行 Dash (Flask) 服务器

ori*_*rie 4 python concurrency flask python-asyncio plotly-dash

我创建了一个 dash 应用程序来显示另一个代码正在收集的信息,我想使用 Python 中的 asyncio 模块同时运行它们。

我的代码使用异步函数,而 Dash 应用程序(基于 Flask)在服务时阻止其他任何内容执行。

我不确定这是否需要打开更多线程。

这是我当前的代码,仅运行主协程。

async def main():
    some code here...

    while True:
        try:
            await client.handle_message()
        except ConnectionClosedError as error:
            logger.error(error)
    
        for strategy in strategies:
            await asyncio.create_task(...)
            some code here...

async def run_dashboard():
    app = create_app()
    app.run_server('0.0.0.0', 5000, debug=False)


if __name__ == '__main__':
    some code here...

    # Currently just runs the main coroutine
    asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)

如何同时运行 main 和 run_dashboard?

Art*_*rev 7

坦率地说,将 Dash(Flask)与一些异步工作结合在一个进程中并不是一个好的设计,请考虑在不同的进程(即应用​​程序)中运行 Flask 和异步活动。

尽管如此,如果您仍然想在一个进程中运行所有操作,我可以为您提供以下工作示例,请关注评论并询问您是否有任何问题:

from flask import Flask, jsonify
import asyncio
from threading import Thread

# ** Async Part **


async def some_print_task():
    """Some async function"""
    while True:
        await asyncio.sleep(2)
        print("Some Task")


async def another_task():
    """Another async function"""
    while True:
        await asyncio.sleep(3)
        print("Another Task")


async def async_main():
    """Main async function"""
    await asyncio.gather(some_print_task(), another_task())


def async_main_wrapper():
    """Not async Wrapper around async_main to run it as target function of Thread"""
    asyncio.run(async_main())

# *** Flask Part ***:


app = Flask(__name__)


@app.route("/", methods=["GET"])
def index():
    """just some function"""
    return jsonify({"hello": "world"})


if __name__ == '__main__':
    # run all async stuff in another thread
    th = Thread(target=async_main_wrapper)
    th.start()
    # run Flask server
    app.run(host="0.0.0.0", port=9999)
    th.join()
Run Code Online (Sandbox Code Playgroud)

  • 您能详细说明为什么它是糟糕的设计吗?即有哪些风险? (2认同)
  • @SterlingButters,当答案写出来时,Flask 中没有对 `asyncio` 代码的“原生”支持,据我所知(我现在已经 1.5 年没有使用 Flask 了)他们以某种方式添加了它 https://flask .palletsprojects.com/en/2.2.x/async-await/ 。那么为什么它不好呢?asyncio eventloop 在一个线程中工作是很糟糕的。您可以在另一个线程中创建多个异步事件循环,但这会降低应用程序的性能。同样的故事,一个线程中的 asyncio + 其他线程中的 http 请求处理。你只会得到更糟糕的表现。 (2认同)