python - 使用无限循环时 FastAPI 异步路由死锁错误

标签 python asynchronous python-asyncio fastapi python-3.10

我在使用 FastAPI 时遇到一个问题,即在异步路由中使用无限循环时应用程序会陷入死锁。这是我的 FastAPI 应用程序 (fastapi_test.py) 的简化版本:

from fastapi import FastAPI
import random

app = FastAPI()

@app.get("/hello")
async def hello():
    return {"Hello": "World"}

# This route works normally and /hello route keeps working
@app.get("/normal")
def route_normal():
    while True:
        print({"route_normal": random.randint(0, 10)})

# This route causes a whole application deadlock
@app.get("/async")
async def route_async():
    while True:
        print({"route_async": random.randint(0, 10)})

# requirements
# pip install fastapi uvicorn[standard]

当我调用/normal时路由,应用程序保持正常工作。然而,当我调用/async时路线,应用程序陷入僵局,并且没有路线再工作。我正在使用以下命令运行该应用程序:

uvicorn fastapi_test:app --workers 1

我发现在异步路由中使用无限循环时会出现此问题。是否有已知的限制或推荐的方法来处理异步路由中的无限循环以避免死锁?

我还对异步和普通/hello 路由进行了基准测试,异步版本的结果提高了约 50%。

ab -n 100000 -c 1000 http://127.0.0.1:8000/hello

所有这些对我来说真的很困惑。

python 3.10 fastapi==0.104.1

我感谢任何有关解决此问题的指导或见解。谢谢!

最佳答案

这个异步+ while True 循环导致Python 锁定,因为它试图处理循环并且无法切换到其他内部进程。

@app.get("/async")
async def route_async():

这可以通过使用后台任务来解决

from fastapi import BackgroundTasks

@app.get("/async")
async def route_async(background_tasks: BackgroundTasks):
    def background_task():
        while True:
            print({"route_async": random.randint(0, 10)})

    background_tasks.add_task(background_task)
    return {"message": "Background task started"}

完整代码

from fastapi import FastAPI
from fastapi import BackgroundTasks
import random

app = FastAPI()

@app.get("/hello")
async def hello():
    return {"Hello": "World"}

@app.get("/normal")
def route_normal():
    while True:
        print({"route_normal": random.randint(0, 10)})

@app.get("/async")
async def route_async(background_tasks: BackgroundTasks):
    def background_task():
        while True:
            print({"route_async": random.randint(0, 10)})

    background_tasks.add_task(background_task)
    return {"message": "Background task started"}

替代解决方案

允许异步函数休眠

import asyncio
from fastapi import FastAPI
import random

app = FastAPI()

@app.get("/hello")
async def hello():
    return {"Hello": "World"}

@app.get("/normal")
def route_normal():
    while True:
        print({"route_normal": random.randint(0, 10)})

@app.get("/async")
async def route_async():
    while True:
        await asyncio.sleep(0) # do a sleep here so that the main thread can do its magic, at least once per loop, changing the sleep duration will allow the main thread to process other threads longer, please read up more on the specifics
        print({"route_async": random.randint(0, 10)})

关于python - 使用无限循环时 FastAPI 异步路由死锁错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77613533/

相关文章:

python - ModuleNotFoundError : No module named 'apt_pkg' installing deadsnakes repository

python - 如何在OpenCV(Python)中合并边界框

python - Python 3.4'无法分配给函数调用

python 和数据库异步请求(又名即发即弃): how to?

python - 是python3.6新改 'async for'不兼容enumerate

python - 如何防止 asyncio.Task 被取消

c# - 是否可以确定方法是否返回任务并等待它(如果返回)?

javascript - JS (node.js) - 如果我进行异步调用但不等待它完成,是否可以保证完成执行?

python-3.x - 如何确保按给定的顺序处理所有命令(和错误)

python - 如何使用 hypercorn.asyncio.serve(app,quart_cfg) 打开 Debug模式