You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在FastAPI中确保异步函数同一时间仅运行一次?

解决方案

1. 修复异步任务的阻塞问题

你的asyncio_test_prediction里用了time.sleep(30),这是同步阻塞操作,会卡住整个asyncio事件循环,导致其他请求也被阻塞。必须换成异步的asyncio.sleep:

import asyncio
from fastapi import FastAPI

app = FastAPI()

async def asyncio_test_prediction():
    print("Starting asyncio func")
    await asyncio.sleep(30)  # 替换time.sleep为asyncio.sleep
    print("Stopping asyncio func")

2. 存储任务实例并检查运行状态

我们可以用FastAPI的app.state来存储任务实例,这样能在整个应用生命周期中跟踪任务状态。每次调用接口时,先检查任务是否存在且未完成:

异步接口实现(推荐)

# 在app初始化后添加任务存储变量
app.state.prediction_task = None

@app.get('/sempos/start')
async def start_prediction():
    # 检查任务是否存在且未完成
    if app.state.prediction_task is not None and not app.state.prediction_task.done():
        return {"state": "Already running"}
    
    # 创建新任务并存储
    app.state.prediction_task = asyncio.create_task(asyncio_test_prediction())
    return {"state": "Started"}

同步接口实现

如果你的接口不需要异步逻辑,也可以写成同步函数,此时需要手动获取当前事件循环来创建任务:

@app.get('/sempos/start')
def start_prediction():
    loop = asyncio.get_running_loop()
    if app.state.prediction_task is not None and not app.state.prediction_task.done():
        return {"state": "Already running"}
    
    app.state.prediction_task = loop.create_task(asyncio_test_prediction())
    return {"state": "Started"}

3. 额外说明

  • asyncio.create_task是Python 3.7+推荐的创建异步任务的方式,比asyncio.ensure_future更直观。
  • 任务完成后,task.done()会返回True,下次调用接口时会自动创建新任务。
  • 如果需要处理任务的返回值或者异常,可以给任务添加回调函数,比如:
    def task_callback(task):
        try:
            result = task.result()
            print(f"Task result: {result}")
        except Exception as e:
            print(f"Task failed: {e}")
    
    # 创建任务时绑定回调
    task = asyncio.create_task(asyncio_test_prediction())
    task.add_done_callback(task_callback)
    

内容的提问来源于stack exchange,提问作者Tropaion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 05:35:10