使用 Flask 的异步调用方法

Rap*_*odo 9 flask python-3.x python-asyncio

我试图通过 Flask 方法调用阻塞函数,但需要几秒钟,所以我想我可以做一些异步调用来加快速度,但它没有按预期工作。显然使用 asyncio 我不能只是在后台启动一个协程而不等待执行结束,也许我需要使用线程?或者使用 grequest 因为我的阻塞功能正在使用请求...

到目前为止,这是我的代码:

@app.route("/ressource", methods=["GET"])
def get_ressource():
    do_stuff()
    return make_response("OK",200)  

def do_stuff():
  # Some stuff
  fetch_ressource()


async def fetch_ressource():
    return await blocking_function()


def blocking_function():
  # Take 2-3 seconds
  result = request.get('path/to/remote/ressource')
  put_in_database(result)
Run Code Online (Sandbox Code Playgroud)

我听说过 Celeri,但对于只有一个功能来说似乎有点矫枉过正。

pgj*_*nes 6

您可以使用QuartAIOHTTP来完成此操作,其代码应该与给定的 Flask 代码非常熟悉,

@app.route("/ressource", methods=["POST"])
async def get_ressource():
    asyncio.ensure_future(blocking_function())
    return await make_response("OK", 202)  

async def blocking_function():
    async with aiohttp.ClientSession() as session:
        async with session.get('path/to/remote/ressource') as resp:
            result = await resp.text()
    await put_in_database(result)
Run Code Online (Sandbox Code Playgroud)

注意:我已将其更改为 POST 路由,因为它会执行某些操作,并且返回了 202 响应以表明它已触发处理。

如果您想坚持使用 Flask,我建议您使用eventlet并使用spawn(blocking_function)不包含async或 的await内容。

另请注意,我是夸脱的作者。


luc*_*nte 5

现在回答有点晚了,但我对此很感兴趣。

我通过包装函数并通过 调用它来管理它asyncio.run(),但我不知道多次asyncio.run()调用是否是一件好事。

from functools import wraps
from flask import Flask
import asyncio

def async_action(f):
    @wraps(f)
    def wrapped(*args, **kwargs):
        return asyncio.run(f(*args, **kwargs))
    return wrapped

app = Flask(__name__)

@app.route('/')
@async_action
async def index():
    await asyncio.sleep(2)
    return 'Hello world !'

app.run()
Run Code Online (Sandbox Code Playgroud)