title: 异步编程与Tortoise-ORM框架

date: 2025/04/19 00:13:05

updated: 2025/04/19 00:13:05

author: cmdragon

excerpt:

异步编程通过async/await语法实现协程,单线程可处理多个并发请求,适合IO密集型场景。Tortoise-ORM专为异步设计,支持完整ORM功能和多种数据库,与Pydantic深度集成。整合FastAPI时,通过register_tortoise初始化ORM,使用in_transaction管理事务,确保操作原子性。常见问题包括未使用await返回协程对象和事件循环关闭错误,需通过正确的事件循环启动和事务管理解决。

categories:

  • 后端开发
  • FastAPI

tags:

  • 异步编程
  • Tortoise-ORM
  • FastAPI
  • 协程机制
  • 数据库事务
  • Pydantic集成
  • 异步IO


扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长

探索数千个预构建的 AI 应用,开启你的下一个伟大创意

第一章:异步编程基础与Tortoise-ORM框架定位

1.1 异步IO原理与协程机制

当你在快餐店排队时,同步IO就像站在队列中干等取餐,而异步IO则是先下单后去玩手机,听到叫号再取餐。现代Web应用需要同时服务成千上万个这样的"

顾客",这正是异步编程的价值所在。

Python通过async/await语法实现协程:

async def fetch_data():
# 模拟IO操作
await asyncio.sleep(1)
return {"data": "result"} # 事件循环驱动执行
async def main():
task1 = fetch_data()
task2 = fetch_data()
await asyncio.gather(task1, task2) # 并发执行 asyncio.run(main())

关键点解析:

  • async def 声明异步函数(协程)
  • await 将控制权交还事件循环
  • 单个线程可处理多个并发请求

与传统同步模型对比:

指标 同步模式 异步模式
线程使用 1请求1线程 单线程处理多请求
IO等待处理 阻塞 非阻塞
适合场景 CPU密集型 IO密集型

1.2 Tortoise-ORM的异步设计哲学

传统ORM(如Django ORM)在异步环境中会形成性能瓶颈。Tortoise-ORM专为异步而生,其架构设计呈现以下特点:

from tortoise.models import Model
from tortoise import fields class User(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=50)
created_at = fields.DatetimeField(auto_now_add=True) class Meta:
table = "auth_user"

框架核心优势:

  1. 完整的ORM功能支持(关系、事务、聚合)
  2. 原生异步查询接口设计
  3. 支持PostgreSQL/MySQL/SQLite
  4. 与Pydantic深度集成

1.3 整合FastAPI的完整示例

创建具备完整功能的API端点:

from fastapi import FastAPI, Depends
from tortoise.contrib.fastapi import register_tortoise
from pydantic import BaseModel app = FastAPI() # 请求体模型
class UserCreate(BaseModel):
name: str # 响应模型
class UserOut(UserCreate):
id: int
created_at: datetime # 数据库配置
DB_CONFIG = {
"connections": {"default": "sqlite://db.sqlite3"},
"apps": {
"models": {
"models": ["__main__"], # 自动发现当前模块的模型
"default_connection": "default",
}
},
} # 注册Tortoise-ORM
register_tortoise(
app,
config=DB_CONFIG,
generate_schemas=True, # 自动建表
add_exception_handlers=True,
) # 依赖注入数据库连接
async def get_db():
async with in_transaction() as conn:
yield conn @app.post("/users", response_model=UserOut)
async def create_user(user: UserCreate, conn=Depends(get_db)):
"""
创建用户并返回完整数据
使用事务保证原子性操作
"""
db_user = await User.create(**user.dict(), using_db=conn)
return UserOut.from_orm(db_user)

代码要点解析:

  • register_tortoise 实现ORM初始化
  • in_transaction 管理事务作用域
  • using_db 参数确保使用同一连接
  • from_orm 自动转换模型为Pydantic对象

课后Quiz

Q1:当数据库查询未使用await时会导致什么现象?

A. 立即返回查询结果

B. 抛出RuntimeWarning

C. 返回coroutine对象

D. 程序崩溃

正确答案:C

解析:异步函数必须使用await执行,否则将返回未被执行的协程对象,这是常见的初学者错误。

Q2:如何确保多个更新操作在同一个事务中?

A. 使用@transaction装饰器

B. 手动begin/commit

C. 通过in_transaction上下文管理器

D. 所有操作自动在事务中

正确答案:C

解析:async with in_transaction() as conn会创建事务作用域,所有在该上下文中的操作使用同一个连接。

常见报错解决方案

问题1:422 Unprocessable Entity

{
"detail": [
{
"loc": [
"body",
"name"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}

原因分析:

  • 请求体缺少name字段
  • 字段类型不匹配(如数字传字符串)
  • Pydantic模型校验失败

解决方案:

  1. 检查请求体是否符合API文档
  2. 使用Swagger UI进行测试
  3. 查看模型字段定义是否包含required=True

问题2:RuntimeError: Event loop is closed

产生场景:

# 错误写法
async def get_data():
await User.all() # 同步上下文中直接调用
get_data()

正确处理:

async def main():
await get_data() if __name__ == "__main__":
import asyncio asyncio.run(main())

预防建议:

  • 始终通过事件循环启动异步程序
  • 在FastAPI路由中自动管理事件循环
  • 避免在同步代码中直接调用协程

余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长,阅读完整的文章:异步编程与Tortoise-ORM框架 | cmdragon's Blog

往期文章归档:

异步编程与Tortoise-ORM框架的更多相关文章

  1. Paip.Php Java 异步编程。推模型与拉模型。响应式(Reactive)”编程FutureData总结... 1

    Paip.Php  Java 异步编程.推模型与拉模型.响应式(Reactive)"编程FutureData总结... 1.1.1       异步调用的实现以及角色(:调用者 提货单) F ...

  2. ZeroC ICE的远程调用框架 Slice如何帮助我们进行Ice异步编程(AMI,AMD)

    Slice最大的用处就是为我们使用Ice进行编程,代劳绝大部分的重复性代码,并提供一些帮助性的框架代码,如用于AMI和AMD方式进行异步编程的回调框架. 当Slice不为我们生成代码时,我们仍然可以按 ...

  3. ORM框架 和 面向对象编程

    ORM框架: 1.SQLAlchemy:  - 作用   1.提供简单的规则   2.自动转换成SQL语句  - DB first/code first   DB first: 手动创建数据库以及表  ...

  4. Python Twisted网络编程框架与异步编程入门教程

    原作出处:twisted-intro-cn 作者:Dave 译者:杨晓伟 luocheng likebeta 转载声明:版权归原作出处所有,转载只为让更多人看到这部优秀作品合集,如果侵权,请留言告知 ...

  5. 轻量级ORM框架——第一篇:Dapper快速学习

    我们都知道ORM全称叫做Object Relationship Mapper,也就是可以用object来map我们的db,而且市面上的orm框架有很多,其中有一个框架 叫做dapper,而且被称为th ...

  6. ORM框架-VB/C#.Net实体代码生成工具(EntitysCodeGenerate)【ECG】4.5

    摘要:VB/C#.Net实体代码生成工具(EntitysCodeGenerate)[ECG]是一款专门为.Net数据库程序开发量身定做的(ORM框架)代码生成工具,所生成的程序代码基于OO.ADO.N ...

  7. Dapper一个和petapoco差不多的轻量级ORM框架

    我们都知道ORM全称叫做Object Relationship Mapper,也就是可以用object来map我们的db,而且市面上的orm框架有很多,其中有一个框架 叫做dapper,而且被称为th ...

  8. .NET轻量级ORM框架Dapper入门精通

    一.课程介绍 本次分享课程包含两个部分<.NET轻量级ORM框架Dapper修炼手册>和<.NET轻量级ORM框架Dapper葵花宝典>,阿笨将带领大家一起领略轻量级ORM框架 ...

  9. C# 性能优化 之 秒表 Stopwatch。 Dapper一个和petapoco差不多的轻量级ORM框架

    Sweet小马 小马同学的编程日记. C# 性能优化 之 秒表 Stopwatch. 生词解释:Diagnostics[,daɪəg'nɑstɪks] n.诊断学 using System.Diagn ...

  10. C#与C++的发展历程第三 - C#5.0异步编程巅峰

    系列文章目录 1. C#与C++的发展历程第一 - 由C#3.0起 2. C#与C++的发展历程第二 - C#4.0再接再厉 3. C#与C++的发展历程第三 - C#5.0异步编程的巅峰 C#5.0 ...

随机推荐

  1. GD32F4xx FLASH存储

    一.GD32F4xx的内存 GD32F4xx的内存结构由:主存储器.系统信息存储器.一次性编程区域和选项字节等 4 部分组成. 主存储器:用来存放代码和数据常数(如 const 类型的数据).分为 2 ...

  2. 解锁数据潜力,天翼云TeleDB为企业数智蝶变添力赋能!

    近日,第15届中国数据库技术大会(DTCC2024)在北京召开.大会以"自研创新 数智未来"为主题,重点围绕向量数据库与向量检索技术实践.数据治理与数据资产管理.云原生数据库开发与 ...

  3. MySQL主从复制-原理实战

    一.原理 主从复制架构图:主从复制原理: Mysql 中有一种日志叫做 bin 日志(二进制日志).这个日志会记录下所有修改了数据库的SQL 语句(insert,update,delete,creat ...

  4. SaaS+AI应用架构:业务场景、智能体、大模型、知识库、传统工具系统

    大家好,我是汤师爷~ 在SaaS与AI应用的演进过程中,合理的架构设计至关重要.本节将详细介绍其五个核心层次: 业务场景层:发现和确定业务场景 智能体层:构建可复用的智能应用 大模型层:采用最合适的大 ...

  5. 用豆包+Kimi,一分钟生成想要的PPT!

    大家好!在快节奏的现代社会,时间就是金钱.对于经常需要制作PPT的朋友们来说,如何快速.高效地完成演示文稿的制作一直是个头疼的问题.今天,我要给大家介绍如何利用AI工具:豆包+kimi,让你在一分钟内 ...

  6. Java后台获取微信小程序用户信息、openid

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  7. Datagrip 破解

    题记部分 方法一 [参考链接]:DataGrip 2023.2最新安装使用教程(附激活码,亲测好用)_糖果果爱分享的技术博客_51CTO博客 [软件版本]:datagrip-2023.3.4.win ...

  8. 震撼揭秘:LLM幻觉如何颠覆你的认知!

    LLM幻觉 把幻觉理解为训练流水线中的一种涌现认知效应 Prashal Ruchiranga Robina Weermeijer 在 Unsplash 上的照片 介绍 在一个名为<深入剖析像Ch ...

  9. C#方法练习

    提示用户输入用户名和密码,写一个方法来判断用户输入的是否正确,返回给用户一个登陆结果,并且还要单独的返回给用户一个登陆信息 ,如果用户名错误,除了返回登陆结果之外,还要返回一个 "用户名错误 ...

  10. 机器人技术的突破让OpenAI过时了

    机器人技术的突破让OpenAI过时了 Ignacio de Gregorio 最近,Figure AI,一家价值数十亿美元的AI机器人公司,宣布取消与OpenAI的合作伙伴关系,这一举动看起来是相当大 ...