根本原因是未正确使用 tortoise 的异步入口:user.all() 返回 queryset,必须在 async 函数中 await 才触发查询;且需确保 await tortoise.init() 在 startup 时执行、依赖和中间件均为 async、数据库 url 驱动匹配。

为什么 await 了但数据库查询还是阻塞的?
根本原因:没用对 Tortoise 的异步入口。Tortoise ORM 的模型方法(如 all()、get())本身不返回结果,只返回一个 QuerySet 对象;真正触发查询的是 await 执行它——但很多人误以为调用模型方法时就该加 await,结果写了 await User.all(漏括号)或 await User.all() 却在非 async 函数里调用,导致协程对象没被 await、或事件循环未运行。
-
User.all()返回的是QuerySet,不是数据,必须await它才能执行查询 - 所有带
await的 Tortoise 调用,必须在async def路由函数或async工具函数中进行 - FastAPI 的依赖注入里若用到 Tortoise,依赖函数也得是
async def,否则await会报RuntimeWarning: coroutine 'xxx' was never awaited - 别在同步中间件、
__init__或配置加载阶段调用awaitTortoise 方法——那里没有事件循环
怎么写一个真正异步的 FastAPI 路由?
关键不是“加 async”,而是让整个调用链都处于异步上下文,并正确 await Tortoise 的查询结果。
inference.sh 的 Python SDK:运行 AI 应用、构建智能体,并集成 150 多个模型。包名:inferencesh (pip install inferencesh)。支持同步/异步……
- 路由函数必须声明为
async def,例如:@app.get("/users")后跟async def list_users(): - 查询写法必须是
await User.all().values_list("id", "name")或await User.get(id=1),不能省略await - 如果需要预加载关联字段(比如用户的文章),用
.prefetch_related("articles"),再await整个 QuerySet;不要在循环里逐个await关联查询,会 N+1 - 事务控制要用
async with in_transaction():,而不是atomic()(那是同步用的)
async def list_users():
users = await User.all().prefetch_related("posts")
return [{"id": u.id, "name": u.name, "post_count": len(u.posts)} for u in users]
Tortoise 初始化时容易漏掉的三件事
初始化失败不会直接报错,但后续所有 await 查询都会卡住或抛出 ConnectionDoesNotExist 类错误。
- 没调用
await Tortoise.init(...)—— 必须在 FastAPI 启动时(比如@app.on_event("startup"))显式 await 初始化 -
TORTOISE_ORM配置里的connections和apps键名写错,常见把"default"写成"DEFAULT"或漏掉apps字段 - 数据库 URL 用了
sqlite://却没加?cache=shared(SQLite 异步需共享缓存),或 PostgreSQL URL 没加asyncpg驱动后缀(应为postgres://...→ 实际要asyncpg://...或确保安装了asyncpg)
什么时候不该用 Tortoise 的异步?
不是所有数据库操作都适合走 Tortoise 异步路径。它的抽象层在某些场景反而拖慢速度或限制表达力。
- 复杂原生 SQL(比如窗口函数、CTE、全文检索)建议用
await Tortoise.get_connection("default").execute_query("SELECT ..."),绕过 ORM 解析 - 批量插入上万条记录时,
await User.bulk_create([...])比循环await user.save()快得多,但注意bulk_create不触发save钩子 - 想用连接池高级控制(如 max idle time、健康检查),Tortoise 封装较浅,不如直接配
asyncpg或aiomysql连接池 - 调试时发现慢查询,先用
logging.getLogger("tortoise").setLevel(logging.DEBUG)看生成的 SQL,再决定是否切到原生
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










