type
date
slug
category
icon
password
1. 问题场景
许多成熟的 Python 库使用同步回调机制,例如:
- 事件系统:pypubsub, blinker, django.dispatch
- 信号框架:Qt signals, GTK signals
- Web 框架钩子:Flask before_request, FastAPI middleware
- 消息队列回调:Celery task callbacks
当需要在这些同步回调中执行异步操作时,如何正确集成?
2. 核心挑战
问题:同步框架无法直接处理协程
调用
async def 函数返回协程对象,不会自动执行。协程需要事件循环调度才能运行。3. 解决方案:create_task 包装
核心模式:lambda 包装 + create_task 调度
- lambda 包装:创建同步函数适配器
- create_task:将协程调度到事件循环
- Fire-and-forget:回调立即返回,任务后台运行
调用流程图
4. 何时使用异步处理器?
经验法则:操作耗时 > 10ms → 考虑异步
场景 | 推荐方案 | 原因 |
网络 I/O | 异步 | HTTP 请求、数据库查询耗时 100ms-1s |
文件 I/O | 异步(大文件) | 读写大文件会阻塞事件循环 |
硬件通信 | 异步 | 串口、CAN、Modbus 等耗时 10ms-2s |
调用异步 API | 异步(强制) | await 只能在 async 函数内使用 |
纯内存操作 | 同步 | 配置更新、状态切换微秒级完成 |
简单计算 | 同步 | 无 I/O,无需异步开销 |
5. 并发行为对比
场景:3 个连续的 I/O 操作,每个耗时 1 秒
同步 vs 异步时间线
性能提升:3x(随任务数线性增加)
- 同步:总耗时 3 秒,消息分发被阻塞
- 异步:总耗时 1 秒,消息分发立即完成
同步处理器(顺序执行)
异步处理器(并发执行)
6. 错误处理模式
问题:create_task 异常会被静默忽略
未处理的任务异常不会抛出,导致 Bug 难以追踪。
解决方案 1:添加 done_callback
解决方案 2:包装为 Safe Task
异常处理流程
7. 任务生命周期管理
问题:未保存任务引用会导致泄漏
任务可能被 GC 过早回收,导致不可预期的行为。
解决方案:TaskManager 模式
TaskManager 生命周期
8. 完整实战示例
场景:IoT 设备消息处理系统
输出:
9. 最佳实践总结
推荐做法
- 明确区分同步/异步处理器:I/O 密集 → 异步,纯计算/内存操作 → 同步
- 统一任务管理:保存任务引用避免泄漏,实现优雅关闭机制
- 完善错误处理:使用
done_callback捕获异常,记录日志便于调试
- 控制并发数:使用
Semaphore限制并发任务,避免资源耗尽
避免做法
- 直接订阅协程函数 — 协程永不执行
- 在异步处理器中使用阻塞调用 — 阻塞事件循环
- 忽略任务异常 — 异常被吞掉
- 无限制并发 — 可能创建数千个任务
10. 其他同步框架适配
Qt Signals
Flask Hooks
Celery Callbacks
- Author:felixfixit
- URL:http://www.felixmicrospace.top/article/synchronous_framework_async_pattern
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!




