一个Flask应用程序中的asyncio事件循环

8
什么是在Flask应用中运行asyncio事件循环的最佳方法?
我的 main.py 文件看起来像这样:
if __name__ == '__main__':
    try:
        app.run(host='0.0.0.0', port=8000, debug=True)
    except:
        logging.critical('server: CRASHED: Got exception on main handler')
        logging.critical(traceback.format_exc())
        raise

为了添加异步任务的选项,我需要在运行应用程序之前创建一个event_loop,但即使停止应用程序运行,后台线程仍然挂起(在调试器中可观察到)。
if __name__ == '__main__':
    try:
        app.event_loop = asyncio.get_event_loop()
        app.run(host='0.0.0.0', port=8000, debug=True)
    except:
        logging.critical('server: CRASHED: Got exception on main handler')
        logging.critical(traceback.format_exc())
        raise
    finally:
        app.event_loop.stop()
        app.event_loop.run_until_complete(app.event_loop.shutdown_asyncgens())
        app.event_loop.close()

可以使用以下方法创建异步任务:

def future_callback(fut):
    if fut.exception():
        logging.error(fut.exception())

def fire_and_forget(func, *args, **kwargs):
    if callable(func):
        future = app.event_loop.run_in_executor(None, func, *args, **kwargs)
        future.add_done_callback(future_callback)
    else:
        raise TypeError('Task must be a callable')

我能找到的唯一解决方案是在finally块的末尾添加exit(),但我认为这不是正确的解决方案。

最好不要从Flask调用asyncio代码,抱歉。 - Andrew Svetlov
2个回答

2

我最初采用整个flask应用程序只使用一个事件循环的方法,但由于几个不同的原因,我并不喜欢这种方法。

相反,我创建了一个帮助文件custom_flask_async.py,其中包含两个函数:

import asyncio


def get_set_event_loop():
    try:
        return asyncio.get_event_loop()
    except RuntimeError as e:
        if e.args[0].startswith('There is no current event loop'):
            asyncio.set_event_loop(asyncio.new_event_loop())
            return asyncio.get_event_loop()
        raise e


def run_until_complete(tasks):
    return get_set_event_loop().run_until_complete(asyncio.gather(*tasks))

如果只有在特定请求中使用并等待事件循环,我才会检查并get_set事件循环。因为我主要使用的方式是通过run_until_complete和gather一起使用,所以我也将其包含在辅助函数中。

我也不确定这是否是最佳方法,或者这种方法存在什么缺点,但它绝对适用于我的目的。


使用Python 3.7,您可以使用asyncio.run,对吧?这将创建事件循环并在请求级别关闭它。 - Arvind Sridharan

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接