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

FastAPI与Python中async/await调用是否会进入线程池?

FastAPI中async/await与线程池的关系及和Kotlin协程的对比

核心结论

  • 纯异步IO的async路由:不会进入线程池,和你熟悉的Kotlin协程异步IO场景逻辑一致,由事件循环(类似状态机)调度协程的挂起与恢复。
  • 带阻塞IO的async路由:FastAPI不会自动将阻塞操作丢进线程池,若不手动处理会卡死事件循环;你可以用asyncio.to_thread()或线程池包装阻塞代码,此时任务才会进入线程池执行。
  • FastAPI的同步路由(不带async):默认会在线程池里运行,这也是最佳实践文档建议“别给只有阻塞IO的路由加async”的原因——同步路由的线程池管理是自动的,比手动处理async里的阻塞IO更省心。

和Kotlin协程的差异与共性

共性

两者本质都是基于状态机的协程实现,在纯异步IO场景下,都是通过挂起等待IO完成来切换任务,不需要依赖线程池:

  • Kotlin里用挂起函数做异步IO时,协程会在状态机的调度下挂起,IO完成后恢复执行,无需额外线程。
  • Python asyncio的事件循环也是单线程内调度协程,遇到IO挂起时就切换到其他就绪协程,等IO回调触发再继续当前协程。

差异

  • 线程调度灵活性:Kotlin协程支持多线程调度器(比如Dispatchers.Default是线程池,Dispatchers.Main是单线程),可以更灵活地在不同线程间切换协程;而Python asyncio默认是单线程事件循环,跨线程需要手动用线程池或进程池配合。
  • 阻塞操作处理:Kotlin协程里如果调用阻塞代码,你需要显式指定Dispatchers.IO(线程池)来避免阻塞主线程;Python asyncio里则需要用asyncio.to_thread()把阻塞代码丢到线程池,否则会阻塞整个事件循环。

代码示例

纯异步IO(不进线程池)

from fastapi import FastAPI
import aiohttp

app = FastAPI()

@app.get("/async-io")
async def async_io_example():
    async with aiohttp.ClientSession() as session:
        async with session.get("https://example.com") as resp:
            return await resp.text()

这个路由里的aiohttp调用是纯异步IO,全程由asyncio事件循环调度,不会用到线程池。

阻塞IO手动包装(进线程池)

from fastapi import FastAPI
import asyncio
import requests

app = FastAPI()

@app.get("/blocking-in-async")
async def blocking_in_async():
    # 用to_thread把阻塞的requests调用丢进线程池
    result = await asyncio.to_thread(requests.get, "https://example.com")
    return result.text

这里的requests.get是阻塞IO,通过asyncio.to_thread()放到线程池执行,不会阻塞事件循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 01:11:19