# asyncdemo **Repository Path**: edfeff/asyncdemo ## Basic Information - **Project Name**: asyncdemo - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-13 - **Last Updated**: 2026-09-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # asyncio 系统学习课程 用 **58 个可独立运行的示例**,从「阻塞为什么慢」一路讲到「手写事件循环」和「生产级服务组件」。 每一课都自带中文讲解、实测数据、`assert` 自检和延伸思考题,跑完即学完。 - 语言/版本:Python **3.12.8**(`requires-python = ">=3.12"`) - 包管理:**uv** - 依赖:仅 `httpx`(+ 已有的 `fastapi`),其余全部标准库 - 平台:Windows 11(ProactorEventLoop)验证通过;课程中标注了所有 Windows/Linux 差异 - 网络:**默认完全离线**(所有网络示例都跑在 `127.0.0.1` 的本地服务上) --- ## 快速开始 ```powershell uv sync # 安装依赖(只需一次) uv run main.py # 列出全部 58 课 uv run main.py 13 # 运行全局序号第 13 课 uv run main.py 1.3 # 运行编号 1_03 的课(等价 uv run main.py 1_03) uv run main.py ch 7 # 运行第 7 章全部课程(等价 uv run main.py 7.*) uv run main.py list 8 # 只列出第 8 章 uv run main.py all # 依次跑完全部课程(自检用,约 2 分钟) ``` 也可以直接跑单个文件: ```powershell uv run python "lessons\02_并发编排\2_05_取消机制.py" ``` > 目录与文件名是中文。为了避免在终端里手打中文路径,推荐统一用 `uv run main.py <编号>`。 > 如果控制台中文乱码,先执行 `chcp 65001`(课程文件内部已强制 UTF-8 输出)。 --- ## 学习路径 | 阶段 | 章节 | 目标 | 建议时间 | |---|---|---|---| | 入门 | 00 → 01 → 02 | 理解并发本质、会写正确的并发代码 | 3~5 小时 | | 进阶 | 03 → 04 → 05 | 掌握流控、资源管理、与线程/进程协作 | 4~6 小时 | | 实战 | 06 → 08 | 写得出网络服务、爬虫、后台 worker、Web 应用 | 6~8 小时 | | 深入 | 07 → 09 | 读懂 asyncio 内部实现,能排障、能调优、能跟进版本演进 | 4~6 小时 | **三条推荐路线:** 1. **零基础 → 能用**:`0.1 → 0.2 → 1.1 → 1.3 → 1.4 → 2.1 → 2.2 → 2.4 → 2.5 → 3.4 → 5.1 → 5.2 → 8.1` 2. **会用 → 写好生产代码**:`8.1 → 2.2 → 2.5 → 2.6 → 3.1 → 3.4 → 3.5 → 4.2 → 4.3 → 8.2 → 8.3 → 8.5 → 8.6 → 8.8` 3. **想搞懂原理**:`0.4 → 1.4 → 7.1 → 7.2 → 7.3 → 7.5 → 7.4 → 7.6 → 7.7` --- ## 完整课程索引 ### 00 预备知识(为什么需要 asyncio) | 编号 | 课程 | 一句话说明 | |---|---|---| | 0.1 | 并发与IO多路复用 | 阻塞/并发/并行辨析,用 `selectors` 亲手做单线程多路复用 | | 0.2 | 同步串行的代价 | 真实 TCP 慢服务实测:串行 900ms vs 多线程 150ms,以及线程的代价(C10K) | | 0.3 | 线程对比协程 | 同样 200 个 I/O 任务的资源对比、竞态复现、GIL 实测、内存量级差 | | 0.4 | 从生成器到await | 手写 generator 调度器,再手动 `.send()` 驱动真实协程,看穿 await 的本质 | | 0.5 | CPU密集与IO密集 | 四种执行方式基准;CPU 密集协程如何「饿死」整个事件循环 | ### 01 协程与事件循环入门 | 编号 | 课程 | 一句话说明 | |---|---|---| | 1.1 | 协程对象 | 调用 `async def` 不执行、忘记 await 的后果、协程对象一次性 | | 1.2 | asyncio_run内幕 | 手动重放 `asyncio.run` 的 7 个步骤、Runner 复用、loop_factory、跨 loop 禁忌 | | 1.3 | 创建任务 | `create_task` 只报名不执行;并发的标准写法;1 万个任务的开销实测 | | 1.4 | await是唯一让出点 | 2 万次 `await` 却 0 次让出的实证;真正的挂起点清单;忙等反模式 | | 1.5 | 任务自省 | `all_tasks`/`get_stack`/`cancelling`;手写任务监控器与泄漏检测 | | 1.6 | 发射后不管的坑 | 任务被 GC 吃掉、异常被吞、退出时清理没跑完 —— 三个致命坑与正确模式 | ### 02 并发编排 | 编号 | 课程 | 一句话说明 | |---|---|---| | 2.1 | gather | 结果顺序保证、`return_exceptions`、异常后兄弟任务变孤儿的危险默认行为 | | 2.2 | taskgroup结构化并发 | 结构化并发、ExceptionGroup、双向取消传播、嵌套与整组超时、实现原理 | | 2.3 | wait与as_completed | 完成顺序消费、竞速(hedged request)、Top-K、预算降级三大实战模式 | | 2.4 | 超时控制 | wait_for/timeout/timeout_at 分工、单调时钟、deadline 传播、双层重试超时 | | 2.5 | 取消机制 | 取消生命周期、清理中 await 的实测结论、shield、僵尸任务、批量取消标准流程 | | 2.6 | 异常处理 | 任务异常的三种去向、ExceptionGroup 分类处理、异常链、done_callback、全局兜底 | ### 03 同步原语与流控 | 编号 | 课程 | 一句话说明 | |---|---|---| | 3.1 | 协程也有竞态 | 丢失更新、缓存击穿、超卖三类竞态复现;single-flight 最优解 | | 3.2 | lock与event | Lock 不可重入与死锁、临界区粒度的性能差、Event 三种用法、threading.Lock 冻结实测 | | 3.3 | condition_semaphore_barrier | 限流、条件等待、集合点;Barrier 在 3.12 的四个实测坑 | | 3.4 | queue生产者消费者 | task_done/join 精确语义、取消安全性实测、三种优雅关闭方案、可复用 worker 池 | | 3.5 | 背压与限流 | 背压四策略、令牌桶、匀速器、批处理、值合并,全部带真实速率验证 | | 3.6 | contextvars | 全局变量串味、Task 上下文隔离、跨线程传播、日志自动带 request_id | ### 04 异步迭代与资源管理 | 编号 | 课程 | 一句话说明 | |---|---|---| | 4.1 | 异步迭代器 | async for 协议、异步生成器、自动翻页迭代器、break 后清理时机的实测 | | 4.2 | 异步上下文管理器 | `__aenter__/__aexit__`、asynccontextmanager、取消安全清理、AsyncExitStack、四个可抄组件 | | 4.3 | 异步生成器生命周期 | asend/athrow/aclose;「迟到的清理」实测;GeneratorExit 规则;最佳实践清单 | | 4.4 | 流式算子 | 自实现 map/filter/batch/window/merge/conflate 等算子;`wait_for(anext())` 杀死上游的陷阱 | | 4.5 | 异步流水线 | 可复用 Pipeline 组件:阶段并发、背压、错误隔离、死信、逐级排空停机 | ### 05 线程与进程互操作 | 编号 | 课程 | 一句话说明 | |---|---|---| | 5.1 | 阻塞会冻结事件循环 | 一次 200ms 阻塞让全部请求延迟翻倍的实测;15 个隐形阻塞源;loop lag 监控器 | | 5.2 | to_thread | 用法、上下文传播、默认线程池饱和、**取消不能中断线程**的实测、舱壁隔离、SDK 封装模板 | | 5.3 | 执行器 | run_in_executor 三种形态、Future 两层取消语义、wrap_future、pickle 限制实测、生命周期 | | 5.4 | CPU密集与进程池 | 四方式基准、chunksize 调优、序列化开销、initializer/max_tasks_per_child、生产封装 CpuPool | | 5.5 | 跨线程桥接 | run_coroutine_threadsafe、call_soon_threadsafe、后台常驻 loop、三个必踩的坑、架构全景图 | | 5.6 | 同步代码调用异步 | 五种场景解法、Runner 复用的 13 倍差距、双 API 库设计、渐进式迁移路线、七条禁忌 | ### 06 网络与子进程 IO | 编号 | 课程 | 一句话说明 | |---|---|---| | 6.1 | tcp回显服务器 | streams 四种读法、write/drain 背压、200 并发实测、优雅关闭(含 3.12 的 wait_closed 变化) | | 6.2 | tcp客户端 | 三种超时、指数退避重连、长度前缀分帧、单连接多路复用、最小连接池 | | 6.3 | 手写迷你HTTP服务器 | 150 行实现 HTTP/1.1:解析、路由、keep-alive、chunked 流式响应、httpx 压测 | | 6.4 | 聊天室广播 | Hub + 每连接发送队列的广播架构、慢客户端治理、优雅关闭、五个经典坑 | | 6.5 | udp数据报 | DatagramProtocol、回调转协程、100 并发丢包实测、在 UDP 上做可靠传输 | | 6.6 | 子进程 | exec vs shell、communicate vs 流式读、stdout/stderr 死锁、超时杀进程、12 路并发 | | 6.7 | httpx并发请求 | Client 复用的价值、限流+重试模板、流式下载、异常分类、ASGITransport 进程内调用 | ### 07 底层原理 | 编号 | 课程 | 一句话说明 | |---|---|---| | 7.1 | future | Future 全部 API、await 的 yield 机制、回调式 API 适配器、六个坑 | | 7.2 | 回调与调度 | call_soon/later/at、一轮迭代做了什么、手写 sleep、四种定时器模式、定时精度实测 | | 7.3 | task_step内幕 | 手写 100 行 MyTask 跑通并发/异常/取消,逐行对照 CPython 源码,eager task 实测 | | 7.4 | transport与protocol | 两层 I/O 架构、流控水位、close vs abort、TLS、回调式 vs 协程式性能对比 | | 7.5 | 手写事件循环 | 不依赖 asyncio 实现 Future/Task/Loop/sleep/gather,并用真实 socket 跑并发 echo 服务 | | 7.6 | add_reader与非阻塞socket | BlockingIOError、add_reader 手写服务器、封装成 await、SelectorEventLoop 源码走读 | | 7.7 | 调试模式 | debug 模式的检查项、慢回调定位、exception handler、任务快照转储、剖析工具、七条告警速查 | ### 08 工程化与实战 | 编号 | 课程 | 一句话说明 | |---|---|---| | 8.1 | 十四大反模式 | 14 个反模式逐个现场复现 + 正确写法 + 一句话判据(全课程的「体检表」) | | 8.2 | 并发爬虫 | 生产级爬虫:限流/重试/去重/超时/深度控制/优雅退出/指标/落地,内置离线模拟站点 | | 8.3 | 优雅停机 | 跨平台信号处理、分阶段停机组件、完整时间线实测、容器/K8s 注意事项 | | 8.4 | 周期调度器 | 漂移问题实测、无漂移调度、防重叠、misfire、退避、抖动、cron 计算、选型建议 | | 8.5 | 后台worker池 | 200 行生产级 WorkerPool:优先级/幂等/背压/重试/死信/扩缩容/看门狗/停机 | | 8.6 | fastapi中的asyncio | async vs def 路由实测、40 线程上限、lifespan、BackgroundTasks、SSE、依赖取消、并发扩展性 | | 8.7 | 性能调优 | 定位三板斧、任务粒度、原语开销、eager task、批处理收益、微观开销、横向扩展、优化清单 | | 8.8 | 测试异步代码 | 24 个真实通过的 unittest 用例:假时钟、Event 编排、AsyncMock、取消/超时、ASGI 测试 | ### 09 版本演进 | 编号 | 课程 | 一句话说明 | |---|---|---| | 9.1 | py311与312新特性 | TaskGroup/ExceptionGroup/timeout/Barrier/Runner/eager_task_factory/loop_factory 全部可运行验证 | | 9.2 | py313及以后 | 特性探测器、Queue.shutdown 兼容层、free-threading 影响、弃用时间线、面向未来的编码准则 | --- ## 每一课的统一结构 ```python """【N.M · 课程名】 本课要点 … # 学完能回答什么问题 运行: uv run main.py N.M """ # ① 概念讲解(打印) ② 现场实测(带 +xxx ms 时间线) # ③ assert 自检 ④ 小结 + 延伸思考 ``` - 每个文件都能单独运行,互不依赖(没有跨文件 import) - 关键结论都有 `assert`,跑通即验证通过(退出码 0) - 单课运行时间基本在 10 秒以内 - 涉及平台差异的地方就地标注(Windows / Linux) --- ## Windows 平台注意事项(本机实测结论) | 项目 | 结论 | 相关课程 | |---|---|---| | 默认事件循环 | `ProactorEventLoop`(IOCP) | 1.2 | | `loop.add_reader/add_writer` | **不支持**(NotImplementedError),需 `loop_factory=SelectorEventLoop` | 7.6 | | `loop.add_signal_handler` | **不支持**,需用 `signal.signal` + `call_soon_threadsafe` | 8.3 | | 子进程 `create_subprocess_exec` | Proactor 支持;SelectorEventLoop **不支持** | 6.6 | | `create_datagram_endpoint`(UDP) | Proactor 支持 | 6.5 | | 定时器精度 | 约 **15.6ms**(`loop._clock_resolution = 0.015625`),毫秒级节拍不可靠 | 3.5 / 7.2 | | `Queue.shutdown()` | 3.13+ 才有,3.12 需自己实现关闭协议 | 3.4 / 9.2 | | `uvloop` | 不支持 Windows | 8.7 | | `Server.wait_closed()` | 3.12 起会等所有 handler 结束;handler 不关 writer 会导致它一直等 | 6.1 / 7.4 | | 进程池启动成本 | 约 100~150ms(spawn),必须复用并预热 | 5.4 | --- ## 目录结构 ``` asyncdemo/ ├── main.py # 课程导航器(列表 / 按编号运行) ├── pyproject.toml # uv 项目配置(httpx + fastapi) ├── README.md # 本文件 ├── docs/ │ └── cheatsheet.md # API 速查 + 反模式速查 + 排障流程 └── lessons/ # 10 章 58 课 ├── 00_预备知识/ (5) ├── 01_协程与事件循环入门/ (6) ├── 02_并发编排/ (6) ├── 03_同步原语与流控/ (6) ├── 04_异步迭代与资源管理/ (5) ├── 05_线程与进程互操作/ (6) ├── 06_网络与子进程IO/ (7) ├── 07_底层原理/ (7) ├── 08_工程化与实战/ (8) └── 09_版本演进/ (2) ``` --- ## 可直接抄进项目的组件清单 课程里这些组件是「生产可用」级别,可以整段复制: | 组件 | 位置 | 用途 | |---|---|---| | `LoopLagMonitor` | 5.1 | 事件循环延迟监控(发现阻塞的最灵敏指标) | | `spawn()` + 引用集合 | 1.6 | 安全的 fire-and-forget | | `cancel_and_wait()` | 2.5 | 批量取消任务并确认退出 | | `TokenBucket` / `PacedLimiter` / `Batcher` / `LatestValue` | 3.5 | 限流、匀速、批处理、值合并 | | `RateLimitedExecutor` | 3.5 | 并发 + 速率双限执行器 | | 流式算子库(`amap/afilter/abatch/awindow/amerge/...`) | 4.4 | 异步数据流处理 | | `Pipeline` | 4.5 | 多阶段流水线(背压 + 重试 + 死信 + 停机) | | `AsyncClientWrapper` | 5.2 | 同步 SDK → 异步接口(独立池 + 限流 + 超时) | | `SyncClient` / `AsyncClient` 双门面 | 5.6 | 一份异步内核,两套 API | | `CpuPool` | 5.4 | 常驻进程池(预热 + 限流 + 超时 + 指标) | | `MultiplexedClient` / `ConnectionPool` | 6.2 | 单连接多路复用、最小连接池 | | `ChatHub` + 每连接发送队列 | 6.4 | 长连接广播服务骨架 | | `MiniHTTPServer` | 6.3 | 教学级 HTTP/1.1 服务器 | | `MiniLoop` / `MiniTask` / `MiniFuture` | 7.5 / 7.3 | 手写事件循环(学习用) | | `dump_tasks()` | 7.7 | 任务快照转储(排查 hang/死锁) | | `Crawler` | 8.2 | 生产级并发爬虫 | | `SignalWatcher` / `GracefulShutdown` | 8.3 | 跨平台信号 + 分阶段停机 | | `Scheduler` / `Job` | 8.4 | 周期任务调度器 | | `WorkerPool` | 8.5 | 后台任务池(优先级/幂等/死信/扩缩容) | | `FakeClock` + 测试骨架 | 8.8 | 异步代码的确定性测试 | | `QueueShutdownCompat` | 9.2 | 跨版本队列关闭协议 | --- ## 常见问题 **Q:中文路径在 PowerShell 里乱码 / 跑不起来?** 用 `uv run main.py <编号>`(导航器内部用 Python 的 Unicode API 传参,不受控制台代码页影响)。 输出乱码时执行 `chcp 65001`,或设置 `$env:PYTHONIOENCODING="utf-8"`。 **Q:某一课卡住不退出?** 课程里刻意演示了死锁/僵尸任务等场景,但都带了停止标志与超时兜底。 若真的卡住,`Ctrl+C` 两次即可;也可以临时用 `python -X faulthandler -c "import faulthandler,runpy,sys; faulthandler.dump_traceback_later(20, exit=True); runpy.run_path(sys.argv[1], run_name='__main__')" <文件>` 打印卡住时的栈。 **Q:能不能加练习题?** 本课程的设计是「每课自带 assert 自检 + 延伸思考题」,跑通即验证。 想要动手练习,推荐:把每课最后的「延伸思考」当题目,改代码 → 跑 assert → 观察输出变化。 **Q:Linux/macOS 上能跑吗?** 能。所有课程都不依赖 Windows 专有 API;平台差异处已用 `sys.platform` 判断或注释说明。 差异最大的是 7.6(Linux 上 Proactor 相关结论不适用,但代码会自动走 SelectorEventLoop 分支)。 --- ## 延伸阅读 - 官方文档:`asyncio` 章节(尤其是 High-level API / Low-level API / Developer Guide 三部分) - 每个版本的 *What's New in Python*(asyncio 小节) - CPython 源码:`Lib/asyncio/base_events.py`、`tasks.py`、`taskgroups.py`、`timeouts.py`、`locks.py`、`queues.py`、`streams.py` - PEP 492(async/await)、PEP 654(ExceptionGroup)、PEP 703(free-threading) - 书:*Using Asyncio in Python*(Caleb Hattingh)、*Python Concurrency with asyncio*(Matthew Fowler)