异步编程与Tortoise-ORM框架
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

扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长
第一章:异步编程基础与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"
框架核心优势:
- 完整的ORM功能支持(关系、事务、聚合)
- 原生异步查询接口设计
- 支持PostgreSQL/MySQL/SQLite
- 与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模型校验失败
解决方案:
- 检查请求体是否符合API文档
- 使用Swagger UI进行测试
- 查看模型字段定义是否包含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
往期文章归档:
- FastAPI数据库集成与事务管理 | cmdragon's Blog
- FastAPI与SQLAlchemy数据库集成 | cmdragon's Blog
- FastAPI与SQLAlchemy数据库集成与CRUD操作 | cmdragon's Blog
- FastAPI与SQLAlchemy同步数据库集成 | cmdragon's Blog
- SQLAlchemy 核心概念与同步引擎配置详解 | cmdragon's Blog
- FastAPI依赖注入性能优化策略 | cmdragon's Blog
- FastAPI安全认证中的依赖组合 | cmdragon's Blog
- FastAPI依赖注入系统及调试技巧 | cmdragon's Blog
- FastAPI依赖覆盖与测试环境模拟 | cmdragon's Blog
- FastAPI中的依赖注入与数据库事务管理 | cmdragon's Blog
- FastAPI依赖注入实践:工厂模式与实例复用的优化策略 | cmdragon's Blog
- FastAPI依赖注入:链式调用与多级参数传递 | cmdragon's Blog
- FastAPI依赖注入:从基础概念到应用 | cmdragon's Blog
- FastAPI中实现动态条件必填字段的实践 | cmdragon's Blog
- FastAPI中Pydantic异步分布式唯一性校验 | cmdragon's Blog
- 掌握FastAPI与Pydantic的跨字段验证技巧 | cmdragon's Blog
- FastAPI中的Pydantic密码验证机制与实现 | cmdragon's Blog
- 深入掌握FastAPI与OpenAPI规范的高级适配技巧 | cmdragon's Blog
- Pydantic字段元数据指南:从基础到企业级文档增强 | cmdragon's Blog
- Pydantic Schema生成指南:自定义JSON Schema | cmdragon's Blog
- Pydantic递归模型深度校验36计:从无限嵌套到亿级数据的优化法则 | cmdragon's Blog
- Pydantic异步校验器深:构建高并发验证系统 | cmdragon's Blog
- Pydantic根校验器:构建跨字段验证系统 | cmdragon's Blog
- Pydantic配置继承抽象基类模式 | cmdragon's Blog
- Pydantic多态模型:用鉴别器构建类型安全的API接口 | cmdragon's Blog
- FastAPI性能优化指南:参数解析与惰性加载 | cmdragon's Blog
- FastAPI依赖注入:参数共享与逻辑复用 | cmdragon's Blog
- FastAPI安全防护指南:构建坚不可摧的参数处理体系 | cmdragon's Blog
- FastAPI复杂查询终极指南:告别if-else的现代化过滤架构 | cmdragon's Blog
- FastAPI 核心机制:分页参数的实现与最佳实践 | cmdragon's Blog
- FastAPI 错误处理与自定义错误消息完全指南:构建健壮的 API 应用 ️ | cmdragon's Blog
- FastAPI 自定义参数验证器完全指南:从基础到高级实战 | cmdragon's Blog
- FastAPI 参数别名与自动文档生成完全指南:从基础到高级实战 | cmdragon's Blog
- FastAPI Cookie 和 Header 参数完全指南:从基础到高级实战 | cmdragon's Blog
异步编程与Tortoise-ORM框架的更多相关文章
- Paip.Php Java 异步编程。推模型与拉模型。响应式(Reactive)”编程FutureData总结... 1
Paip.Php Java 异步编程.推模型与拉模型.响应式(Reactive)"编程FutureData总结... 1.1.1 异步调用的实现以及角色(:调用者 提货单) F ...
- ZeroC ICE的远程调用框架 Slice如何帮助我们进行Ice异步编程(AMI,AMD)
Slice最大的用处就是为我们使用Ice进行编程,代劳绝大部分的重复性代码,并提供一些帮助性的框架代码,如用于AMI和AMD方式进行异步编程的回调框架. 当Slice不为我们生成代码时,我们仍然可以按 ...
- ORM框架 和 面向对象编程
ORM框架: 1.SQLAlchemy: - 作用 1.提供简单的规则 2.自动转换成SQL语句 - DB first/code first DB first: 手动创建数据库以及表 ...
- Python Twisted网络编程框架与异步编程入门教程
原作出处:twisted-intro-cn 作者:Dave 译者:杨晓伟 luocheng likebeta 转载声明:版权归原作出处所有,转载只为让更多人看到这部优秀作品合集,如果侵权,请留言告知 ...
- 轻量级ORM框架——第一篇:Dapper快速学习
我们都知道ORM全称叫做Object Relationship Mapper,也就是可以用object来map我们的db,而且市面上的orm框架有很多,其中有一个框架 叫做dapper,而且被称为th ...
- ORM框架-VB/C#.Net实体代码生成工具(EntitysCodeGenerate)【ECG】4.5
摘要:VB/C#.Net实体代码生成工具(EntitysCodeGenerate)[ECG]是一款专门为.Net数据库程序开发量身定做的(ORM框架)代码生成工具,所生成的程序代码基于OO.ADO.N ...
- Dapper一个和petapoco差不多的轻量级ORM框架
我们都知道ORM全称叫做Object Relationship Mapper,也就是可以用object来map我们的db,而且市面上的orm框架有很多,其中有一个框架 叫做dapper,而且被称为th ...
- .NET轻量级ORM框架Dapper入门精通
一.课程介绍 本次分享课程包含两个部分<.NET轻量级ORM框架Dapper修炼手册>和<.NET轻量级ORM框架Dapper葵花宝典>,阿笨将带领大家一起领略轻量级ORM框架 ...
- C# 性能优化 之 秒表 Stopwatch。 Dapper一个和petapoco差不多的轻量级ORM框架
Sweet小马 小马同学的编程日记. C# 性能优化 之 秒表 Stopwatch. 生词解释:Diagnostics[,daɪəg'nɑstɪks] n.诊断学 using System.Diagn ...
- 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 ...
随机推荐
- ulimit命令 控制服务器资源
命 令:ulimit功 能:控制shell程序的资源语 法:ulimit [-aHS][-c <core文件上限>][-d <数据节区大小>][-f <文件大 小 ...
- Luogu P2468 SDOI2010 粟粟的书架 题解 [ 紫 ] [ 可持久化线段树 ] [ 二分 ] [ 前缀和 ]
粟粟的书架:二合一的缝合题. 前一半测试点 此时是 \(200\times 200\) 的二维问题,首先考虑暴力怎么写,显然是每次询问把查的全扔进大根堆里,然后一直取堆顶直到满足要求或者取空. 那么这 ...
- 开源的 DeepSeek-R1「GitHub 热点速览」
春节假期回来,一睁眼全是王炸级的开源模型 DeepSeek-R1! GitHub 地址→github.com/deepseek-ai/DeepSeek-R1 DeepSeek-R1 开源还不到一个月, ...
- dotnet CLI推送Nuget
前提: 准备好要发布的包 选择一个打包工具,可以是dotnet CLI.nuget.exe CLI.MSBuild 准备好Nuget官方API Key 自述文件 先必须添加Readme.md到项目 ...
- Java学习记录01
营销核心 营销核心是让利,外围是怎么去让利,三环是公共平台 策略模式学习 意图:定义一系列方法将其封装,并且相互可以替代 目的:解决if-else带来的复杂性和难以维护性 关键实现:多个方法类实现同一 ...
- [ZJOI2019] 语言 题解
不愧是 \(ZJOI\),<最可做的一道题>都让人一头雾水-- 首先将问题转化到链上. 可以将总共的组数转化为每个点可以到达的城市. 明显给每个点建一棵动态开点线段树,维护可以和他通商的点 ...
- JavaUtils - [03] 代码生成器(旧)
题记部分 001 || 引入依赖 <!-- Code Generator --> <dependency> <groupId>com.baomidou</gr ...
- Windows下快捷方式 (*.lnk) 的使用技巧整理
日常应用中,许多软件都会在安装过程最后一步添加多个命令,针对其应用创建快捷方式发送到桌面以及快速启动栏和开始菜单,供人们快速找到并打开.在我的使用习惯中也会将诸多常用的应用右键-发送到-桌面快捷方式来 ...
- Scala查看源码
package com.wyh.day01 /** * 1.代码格式化的快捷键 ctrl+alt+L\ * 2.scala查看源代码的快捷键 ctrl+b */ object ScalaLookSou ...
- CF2067D Object Identification
CF2067D - Object Identification 题目大意 有一个对你公开的 \(x\) 数组和一个对你隐藏的 \(y\) 数组,保证没有任何两个相同的 \(\{x_i, y_i\}\) ...