我想在每次执行flask路径时执行异步函数 . 目前我的abar函数从未执行过 . 你能告诉我为什么吗?非常感谢你:
import asyncio
from flask import Flask
async def abar(a):
print(a)
loop = asyncio.get_event_loop()
app = Flask(__name__)
@app.route("/")
def notify():
asyncio.ensure_future(abar("abar"), loop=loop)
return "OK"
if __name__ == "__main__":
app.run(debug=False, use_reloader=False)
loop.run_forever()
我也尝试将一个阻塞调用放在一个单独的线程中 . 但它仍然没有称之为abar功能 .
import asyncio
from threading import Thread
from flask import Flask
async def abar(a):
print(a)
app = Flask(__name__)
def start_worker(loop):
asyncio.set_event_loop(loop)
try:
loop.run_forever()
finally:
loop.close()
worker_loop = asyncio.new_event_loop()
worker = Thread(target=start_worker, args=(worker_loop,))
@app.route("/")
def notify():
asyncio.ensure_future(abar("abar"), loop=worker_loop)
return "OK"
if __name__ == "__main__":
worker.start()
app.run(debug=False, use_reloader=False)
3 回答
您可以将一些异步功能合并到Flask应用程序中,而无需将它们完全转换为asyncio .
这将阻止Flask响应,直到异步函数返回,但它仍然允许你做一些聪明的事情 . 我已经使用这种模式使用aiohttp并行执行许多外部请求,然后当它们完成时,我又回到传统的瓶子中进行数据处理和模板渲染 .
一个更简单的问题解决方案(在我的偏见视图中)是从Flask切换到Quart . 如果是这样,您的代码段简化为,
如其他答案中所述,Flask app运行是阻塞的,并且不与asyncio循环交互 . 另一方面,Quart是基于asyncio构建的Flask API,所以它应该如你所愿 .
另外,作为更新,Flask-Aiohttp不再是maintained .
出于同样的原因,你不会看到这个印刷品:
永远不会调用
loop.run_forever()
,因为@dirn已经注意到app.run
也在阻塞 .运行全局阻塞事件循环 - 只能运行
asyncio
协同程序和任务,但它与运行阻止Flask应用程序(或通常与任何其他此类东西)不兼容 .如果要使用异步Web框架,则应选择创建为异步的框架 . 例如,现在最流行的可能是aiohttp:
Upd:
关于尝试在后台线程中运行事件循环 . 我没有多少调查,但似乎问题与踏板安全有关:许多asyncio对象不是线程安全的 . 如果您以这种方式更改代码,它将起作用:
但同样,这是一个非常糟糕的主意 . 它有道理:如果你're going to use thread to start asyncio, why don' t just use threads in Flask而不是asyncio?您将拥有所需的Flask和并行化 .
如果我仍然没有说服你,至少看看Flask-aiohttp项目 . 它接近Flask api,我认为你想要做的更好 .