Python 异步编程深度解析:Async/Await 实战

前言

💡 痛点:同步代码执行慢?I/O 密集型任务阻塞?不知道何时用 async?

🎯 解决方案 :从事件循环协程 ,从并发任务性能优化,手把手教你掌握 Python 异步编程。

为什么要学异步编程?
#mermaid-svg-gunG7YC6bLggYV3O{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gunG7YC6bLggYV3O .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gunG7YC6bLggYV3O .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gunG7YC6bLggYV3O .error-icon{fill:#552222;}#mermaid-svg-gunG7YC6bLggYV3O .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gunG7YC6bLggYV3O .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gunG7YC6bLggYV3O .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gunG7YC6bLggYV3O .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gunG7YC6bLggYV3O .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gunG7YC6bLggYV3O .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gunG7YC6bLggYV3O .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gunG7YC6bLggYV3O .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gunG7YC6bLggYV3O .marker.cross{stroke:#333333;}#mermaid-svg-gunG7YC6bLggYV3O svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gunG7YC6bLggYV3O p{margin:0;}#mermaid-svg-gunG7YC6bLggYV3O .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-gunG7YC6bLggYV3O .cluster-label text{fill:#333;}#mermaid-svg-gunG7YC6bLggYV3O .cluster-label span{color:#333;}#mermaid-svg-gunG7YC6bLggYV3O .cluster-label span p{background-color:transparent;}#mermaid-svg-gunG7YC6bLggYV3O .label text,#mermaid-svg-gunG7YC6bLggYV3O span{fill:#333;color:#333;}#mermaid-svg-gunG7YC6bLggYV3O .node rect,#mermaid-svg-gunG7YC6bLggYV3O .node circle,#mermaid-svg-gunG7YC6bLggYV3O .node ellipse,#mermaid-svg-gunG7YC6bLggYV3O .node polygon,#mermaid-svg-gunG7YC6bLggYV3O .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gunG7YC6bLggYV3O .rough-node .label text,#mermaid-svg-gunG7YC6bLggYV3O .node .label text,#mermaid-svg-gunG7YC6bLggYV3O .image-shape .label,#mermaid-svg-gunG7YC6bLggYV3O .icon-shape .label{text-anchor:middle;}#mermaid-svg-gunG7YC6bLggYV3O .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gunG7YC6bLggYV3O .rough-node .label,#mermaid-svg-gunG7YC6bLggYV3O .node .label,#mermaid-svg-gunG7YC6bLggYV3O .image-shape .label,#mermaid-svg-gunG7YC6bLggYV3O .icon-shape .label{text-align:center;}#mermaid-svg-gunG7YC6bLggYV3O .node.clickable{cursor:pointer;}#mermaid-svg-gunG7YC6bLggYV3O .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gunG7YC6bLggYV3O .arrowheadPath{fill:#333333;}#mermaid-svg-gunG7YC6bLggYV3O .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gunG7YC6bLggYV3O .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gunG7YC6bLggYV3O .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gunG7YC6bLggYV3O .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gunG7YC6bLggYV3O .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gunG7YC6bLggYV3O .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gunG7YC6bLggYV3O .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gunG7YC6bLggYV3O .cluster text{fill:#333;}#mermaid-svg-gunG7YC6bLggYV3O .cluster span{color:#333;}#mermaid-svg-gunG7YC6bLggYV3O div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gunG7YC6bLggYV3O .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gunG7YC6bLggYV3O rect.text{fill:none;stroke-width:0;}#mermaid-svg-gunG7YC6bLggYV3O .icon-shape,#mermaid-svg-gunG7YC6bLggYV3O .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gunG7YC6bLggYV3O .icon-shape p,#mermaid-svg-gunG7YC6bLggYV3O .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gunG7YC6bLggYV3O .icon-shape .label rect,#mermaid-svg-gunG7YC6bLggYV3O .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gunG7YC6bLggYV3O .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gunG7YC6bLggYV3O .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gunG7YC6bLggYV3O :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 同步 vs 异步
同步执行
异步执行
⏱️ 阻塞等待
❌ 资源浪费
🐢 I/O 密集型慢
⚡ 非阻塞
✅ 资源高效
🚀 吞吐量高

本文目标: 让你从"会用 async/await 语法"到"理解原理、熟练实战、避免坑"。


一、异步编程核心概念

1.1 同步 vs 异步:为什么需要异步?

异步服务器 同步服务器 客户端 异步服务器 同步服务器 客户端 #mermaid-svg-GwYIdYwiWn2uNgzH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GwYIdYwiWn2uNgzH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GwYIdYwiWn2uNgzH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GwYIdYwiWn2uNgzH .error-icon{fill:#552222;}#mermaid-svg-GwYIdYwiWn2uNgzH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GwYIdYwiWn2uNgzH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GwYIdYwiWn2uNgzH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GwYIdYwiWn2uNgzH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GwYIdYwiWn2uNgzH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GwYIdYwiWn2uNgzH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GwYIdYwiWn2uNgzH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GwYIdYwiWn2uNgzH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GwYIdYwiWn2uNgzH .marker.cross{stroke:#333333;}#mermaid-svg-GwYIdYwiWn2uNgzH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GwYIdYwiWn2uNgzH p{margin:0;}#mermaid-svg-GwYIdYwiWn2uNgzH .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GwYIdYwiWn2uNgzH text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-GwYIdYwiWn2uNgzH .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-GwYIdYwiWn2uNgzH .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-GwYIdYwiWn2uNgzH .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-GwYIdYwiWn2uNgzH .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-GwYIdYwiWn2uNgzH #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-GwYIdYwiWn2uNgzH .sequenceNumber{fill:white;}#mermaid-svg-GwYIdYwiWn2uNgzH #sequencenumber{fill:#333;}#mermaid-svg-GwYIdYwiWn2uNgzH #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-GwYIdYwiWn2uNgzH .messageText{fill:#333;stroke:none;}#mermaid-svg-GwYIdYwiWn2uNgzH .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GwYIdYwiWn2uNgzH .labelText,#mermaid-svg-GwYIdYwiWn2uNgzH .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-GwYIdYwiWn2uNgzH .loopText,#mermaid-svg-GwYIdYwiWn2uNgzH .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-GwYIdYwiWn2uNgzH .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-GwYIdYwiWn2uNgzH .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-GwYIdYwiWn2uNgzH .noteText,#mermaid-svg-GwYIdYwiWn2uNgzH .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-GwYIdYwiWn2uNgzH .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GwYIdYwiWn2uNgzH .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GwYIdYwiWn2uNgzH .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GwYIdYwiWn2uNgzH .actorPopupMenu{position:absolute;}#mermaid-svg-GwYIdYwiWn2uNgzH .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-GwYIdYwiWn2uNgzH .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GwYIdYwiWn2uNgzH .actor-man circle,#mermaid-svg-GwYIdYwiWn2uNgzH line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-GwYIdYwiWn2uNgzH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 阻塞 100ms 请求2/3 排队等待 继续处理请求2 请求1处理中(等待数据库)请求2请求3响应1(总耗时300ms)响应2(总耗时600ms)响应3(总耗时900ms)
异步服务器 客户端 异步服务器 客户端 #mermaid-svg-7oyq0ZuliTwHhVq3{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7oyq0ZuliTwHhVq3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7oyq0ZuliTwHhVq3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7oyq0ZuliTwHhVq3 .error-icon{fill:#552222;}#mermaid-svg-7oyq0ZuliTwHhVq3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7oyq0ZuliTwHhVq3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7oyq0ZuliTwHhVq3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7oyq0ZuliTwHhVq3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7oyq0ZuliTwHhVq3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7oyq0ZuliTwHhVq3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7oyq0ZuliTwHhVq3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7oyq0ZuliTwHhVq3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7oyq0ZuliTwHhVq3 .marker.cross{stroke:#333333;}#mermaid-svg-7oyq0ZuliTwHhVq3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7oyq0ZuliTwHhVq3 p{margin:0;}#mermaid-svg-7oyq0ZuliTwHhVq3 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-7oyq0ZuliTwHhVq3 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-7oyq0ZuliTwHhVq3 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-7oyq0ZuliTwHhVq3 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-7oyq0ZuliTwHhVq3 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-7oyq0ZuliTwHhVq3 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-7oyq0ZuliTwHhVq3 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-7oyq0ZuliTwHhVq3 .sequenceNumber{fill:white;}#mermaid-svg-7oyq0ZuliTwHhVq3 #sequencenumber{fill:#333;}#mermaid-svg-7oyq0ZuliTwHhVq3 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-7oyq0ZuliTwHhVq3 .messageText{fill:#333;stroke:none;}#mermaid-svg-7oyq0ZuliTwHhVq3 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-7oyq0ZuliTwHhVq3 .labelText,#mermaid-svg-7oyq0ZuliTwHhVq3 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-7oyq0ZuliTwHhVq3 .loopText,#mermaid-svg-7oyq0ZuliTwHhVq3 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-7oyq0ZuliTwHhVq3 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-7oyq0ZuliTwHhVq3 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-7oyq0ZuliTwHhVq3 .noteText,#mermaid-svg-7oyq0ZuliTwHhVq3 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-7oyq0ZuliTwHhVq3 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-7oyq0ZuliTwHhVq3 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-7oyq0ZuliTwHhVq3 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-7oyq0ZuliTwHhVq3 .actorPopupMenu{position:absolute;}#mermaid-svg-7oyq0ZuliTwHhVq3 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-7oyq0ZuliTwHhVq3 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-7oyq0ZuliTwHhVq3 .actor-man circle,#mermaid-svg-7oyq0ZuliTwHhVq3 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-7oyq0ZuliTwHhVq3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 等待时处理其他任务 请求1请求2请求3处理中(切换任务)响应1(总耗时100ms)响应2(总耗时100ms)响应3(总耗时100ms)

性能对比:

场景 同步耗时 异步耗时 提升
3 个 I/O 任务(各 100ms) 300ms 100ms 3 倍
10 个 HTTP 请求(各 500ms) 5000ms ~550ms 9 倍
100 个数据库查询(各 50ms) 5000ms ~200ms 25 倍

1.2 核心概念解析

#mermaid-svg-b1smpgOHfJ8PwMZD{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-b1smpgOHfJ8PwMZD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-b1smpgOHfJ8PwMZD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-b1smpgOHfJ8PwMZD .error-icon{fill:#552222;}#mermaid-svg-b1smpgOHfJ8PwMZD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-b1smpgOHfJ8PwMZD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-b1smpgOHfJ8PwMZD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-b1smpgOHfJ8PwMZD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-b1smpgOHfJ8PwMZD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-b1smpgOHfJ8PwMZD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-b1smpgOHfJ8PwMZD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-b1smpgOHfJ8PwMZD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-b1smpgOHfJ8PwMZD .marker.cross{stroke:#333333;}#mermaid-svg-b1smpgOHfJ8PwMZD svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-b1smpgOHfJ8PwMZD p{margin:0;}#mermaid-svg-b1smpgOHfJ8PwMZD .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-b1smpgOHfJ8PwMZD .cluster-label text{fill:#333;}#mermaid-svg-b1smpgOHfJ8PwMZD .cluster-label span{color:#333;}#mermaid-svg-b1smpgOHfJ8PwMZD .cluster-label span p{background-color:transparent;}#mermaid-svg-b1smpgOHfJ8PwMZD .label text,#mermaid-svg-b1smpgOHfJ8PwMZD span{fill:#333;color:#333;}#mermaid-svg-b1smpgOHfJ8PwMZD .node rect,#mermaid-svg-b1smpgOHfJ8PwMZD .node circle,#mermaid-svg-b1smpgOHfJ8PwMZD .node ellipse,#mermaid-svg-b1smpgOHfJ8PwMZD .node polygon,#mermaid-svg-b1smpgOHfJ8PwMZD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-b1smpgOHfJ8PwMZD .rough-node .label text,#mermaid-svg-b1smpgOHfJ8PwMZD .node .label text,#mermaid-svg-b1smpgOHfJ8PwMZD .image-shape .label,#mermaid-svg-b1smpgOHfJ8PwMZD .icon-shape .label{text-anchor:middle;}#mermaid-svg-b1smpgOHfJ8PwMZD .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-b1smpgOHfJ8PwMZD .rough-node .label,#mermaid-svg-b1smpgOHfJ8PwMZD .node .label,#mermaid-svg-b1smpgOHfJ8PwMZD .image-shape .label,#mermaid-svg-b1smpgOHfJ8PwMZD .icon-shape .label{text-align:center;}#mermaid-svg-b1smpgOHfJ8PwMZD .node.clickable{cursor:pointer;}#mermaid-svg-b1smpgOHfJ8PwMZD .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-b1smpgOHfJ8PwMZD .arrowheadPath{fill:#333333;}#mermaid-svg-b1smpgOHfJ8PwMZD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-b1smpgOHfJ8PwMZD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-b1smpgOHfJ8PwMZD .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-b1smpgOHfJ8PwMZD .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-b1smpgOHfJ8PwMZD .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-b1smpgOHfJ8PwMZD .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-b1smpgOHfJ8PwMZD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-b1smpgOHfJ8PwMZD .cluster text{fill:#333;}#mermaid-svg-b1smpgOHfJ8PwMZD .cluster span{color:#333;}#mermaid-svg-b1smpgOHfJ8PwMZD div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-b1smpgOHfJ8PwMZD .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-b1smpgOHfJ8PwMZD rect.text{fill:none;stroke-width:0;}#mermaid-svg-b1smpgOHfJ8PwMZD .icon-shape,#mermaid-svg-b1smpgOHfJ8PwMZD .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-b1smpgOHfJ8PwMZD .icon-shape p,#mermaid-svg-b1smpgOHfJ8PwMZD .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-b1smpgOHfJ8PwMZD .icon-shape .label rect,#mermaid-svg-b1smpgOHfJ8PwMZD .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-b1smpgOHfJ8PwMZD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-b1smpgOHfJ8PwMZD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-b1smpgOHfJ8PwMZD :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 异步编程核心概念
事件循环

Event Loop
协程

Coroutine
任务

Task
Future

期约
📋 任务调度器
🔄 无限循环
⏭️ 任务切换
🎯 可暂停的函数
✨ async def 定义
⏸️ await 暂停
📦 包装协程
🔄 并发执行
✅ 状态追踪
⏳ 异步结果
📮 占位符
🔗 链式调用

概念对比:

概念 说明 类比
事件循环 调度和执行任务的循环 餐厅服务员
协程 可暂停/恢复的函数 厨师(可暂停做菜)
任务 (Task) 协程的包装,用于跟踪状态 订单
Future/Task 异步操作的占位符 取餐号

二、async/await 基础语法

2.1 定义协程函数

python 复制代码
# ===== 协程函数基础 =====

# 1. 定义协程函数(async def)
import asyncio

async def hello():
    """最简单的协程函数"""
    print("Hello!")
    # await 会让出控制权
    await asyncio.sleep(1)
    print("World!")
    return "Done"

# 2. 调用协程(不会立即执行)
# hello()  # ❌ 不会执行,返回协程对象
# hello()  # ❌ 同样不会执行

# 3. 运行协程(必须用事件循环)
async def main():
    result = await hello()
    print(f"Result: {result}")

# 运行方式 1:asyncio.run()(推荐)
asyncio.run(main())

# 运行方式 2:手动创建事件循环
# loop = asyncio.new_event_loop()
# asyncio.set_event_loop(loop)
# try:
#     loop.run_until_complete(main())
# finally:
#     loop.close()

2.2 await 关键字详解

python 复制代码
# ===== await 关键字 =====

async def task1():
    print("Task 1: 开始")
    await asyncio.sleep(1)  # 暂停,等待 1 秒
    print("Task 1: 结束")
    return "Task 1 结果"

async def task2():
    print("Task 2: 开始")
    await asyncio.sleep(2)  # 暂停,等待 2 秒
    print("Task 2: 结束")
    return "Task 2 结果"

async def main():
    # await 只能用在 async 函数中
    result1 = await task1()  # 等待 task1 完成
    print(f"收到: {result1}")
    
    result2 = await task2()  # 等待 task2 完成
    print(f"收到: {result2}")

# 运行
asyncio.run(main())
# 输出:
# Task 1: 开始
# Task 1: 结束
# 收到: Task 1 结果
# Task 2: 开始
# Task 2: 结束
# 收到: Task 2 结果
# 总耗时:3 秒(顺序执行)

print("\n" + "="*50 + "\n")

# ===== 并发执行 =====
async def main_concurrent():
    # 并发执行两个任务
    result1, result2 = await asyncio.gather(
        task1(),  # 不加 await,传协程对象
        task2()
    )
    print(f"收到: {result1}, {result2}")

asyncio.run(main_concurrent())
# 输出:
# Task 1: 开始
# Task 2: 开始
# Task 1: 结束
# Task 2: 结束
# 收到: Task 1 结果, Task 2 结果
# 总耗时:2 秒(并发执行)

2.3 协程 vs 普通函数

python 复制代码
# ===== 协程 vs 普通函数 =====

# 普通函数
def sync_function():
    return "普通函数返回值"

# 协程函数
async def async_function():
    return "协程函数返回值"

# 调用对比
print(f"普通函数: {sync_function()}")  # 立即返回

# 协程函数必须用事件循环
async def test():
    result = await async_function()
    print(f"协程函数: {result}")

asyncio.run(test())

# ===== 类型检查 =====
import inspect

print(f"\n普通函数类型: {type(sync_function)}")  # <class 'function'>
print(f"协程函数类型: {type(async_function)}")  # <class 'coroutine'>
print(f"协程对象类型: {type(asyncio.run(async_function()))}")  # <class 'str'>

print(f"\niscoroutinefunction: {inspect.iscoroutinefunction(async_function)}")  # True
print(f"iscoroutinefunction(普通函数): {inspect.iscoroutinefunction(sync_function)}")  # False

三、事件循环详解

3.1 事件循环原理

渲染错误: Mermaid 渲染失败: Lexical error on line 1. Unrecognized text. graph flowchart A[事件循 -----^

3.2 事件循环操作

python 复制代码
# ===== 事件循环操作 =====

import asyncio
import time

async def sample_task(name, duration):
    """示例任务"""
    print(f"[{name}] 开始")
    await asyncio.sleep(duration)
    print(f"[{name}] 结束")
    return f"{name} 完成"

async def main():
    # 1. 获取当前事件循环
    loop = asyncio.get_running_loop()
    print(f"运行中的事件循环: {loop}")
    
    # 2. 创建任务
    task1 = asyncio.create_task(sample_task("任务1", 1))
    task2 = asyncio.create_task(sample_task("任务2", 2))
    
    # 3. 等待任务完成
    results = await asyncio.gather(task1, task2)
    print(f"结果: {results}")

# 运行
start = time.time()
asyncio.run(main())
print(f"总耗时: {time.time() - start:.2f}秒")

print("\n" + "="*50 + "\n")

# ===== 事件循环的生命周期 =====

async def lifecycle_demo():
    """事件循环生命周期演示"""
    
    # 获取事件循环
    loop = asyncio.get_running_loop()
    print(f"事件循环 ID: {id(loop)}")
    
    # 创建多个任务
    tasks = [
        asyncio.create_task(sample_task(f"任务{i}", i))
        for i in range(1, 4)
    ]
    
    # 等待所有任务
    await asyncio.gather(*tasks)
    
    print("所有任务完成")

asyncio.run(lifecycle_demo())

3.3 事件循环的高级用法

python 复制代码
# ===== 事件循环高级用法 =====

import asyncio
from asyncio import Future

async def task_with_future():
    """手动创建 Future"""
    loop = asyncio.get_running_loop()
    
    # 创建 Future
    future = loop.create_future()
    
    # 在另一个任务中设置结果
    async def set_result():
        await asyncio.sleep(1)
        future.set_result("Future 完成!")
    
    # 并发执行
    await asyncio.gather(
        set_result(),
        future  # 等待 future 完成
    )
    
    print(f"Future 结果: {future.result()}")

asyncio.run(task_with_future())

print("\n" + "="*50 + "\n")

# ===== 延迟执行 =====
async def delayed_execution():
    """延迟执行任务"""
    
    # 方法 1:asyncio.sleep(推荐)
    print("1. 开始 sleep")
    await asyncio.sleep(2)  # 等待 2 秒
    print("1. Sleep 结束")
    
    # 方法 2:loop.call_later
    def callback():
        print("2. 定时回调执行")
    
    loop = asyncio.get_running_loop()
    handle = loop.call_later(1, callback)  # 1 秒后执行
    
    # 方法 3:loop.call_at(绝对时间)
    async def delayed_task():
        await asyncio.sleep(0.5)
        print("3. 延迟任务执行")
    
    await asyncio.sleep(2)  # 等待上面的任务
    # handle.cancel()  # 可以取消定时任务

asyncio.run(delayed_execution())

四、并发任务管理

4.1 asyncio.gather - 并发执行多个协程

python 复制代码
# ===== asyncio.gather 并发执行 =====

import asyncio
import time

async def http_request(url, delay):
    """模拟 HTTP 请求"""
    print(f"请求 {url}...")
    await asyncio.sleep(delay)
    return f"{url} 响应"

async def main_gather():
    """并发执行多个 HTTP 请求"""
    start = time.time()
    
    # 并发执行 5 个请求
    urls = [
        ("https://api.example.com/users", 1),
        ("https://api.example.com/posts", 0.5),
        ("https://api.example.com/comments", 0.8),
        ("https://api.example.com/tags", 0.3),
        ("https://api.example.com/stats", 1.2),
    ]
    
    # 使用 gather 并发执行
    tasks = [http_request(url, delay) for url, delay in urls]
    results = await asyncio.gather(*tasks)
    
    print(f"\n所有响应: {results}")
    print(f"总耗时: {time.time() - start:.2f}秒")  # ~1.2 秒(最长那个)

asyncio.run(main_gather())

print("\n" + "="*50 + "\n")

# ===== gather 返回异常处理 =====

async def may_fail_task(task_id):
    """可能失败的任务"""
    await asyncio.sleep(0.5)
    if task_id == 3:
        raise ValueError(f"任务 {task_id} 失败!")
    return f"任务 {task_id} 完成"

async def main_with_errors():
    """gather 处理异常"""
    
    # 默认行为:任何一个失败,整个 gather 失败
    try:
        results = await asyncio.gather(
            may_fail_task(1),
            may_fail_task(2),
            may_fail_task(3),  # 这个会失败
        )
    except ValueError as e:
        print(f"捕获异常: {e}")
    
    # return_exceptions=True:捕获所有异常
    results = await asyncio.gather(
        may_fail_task(1),
        may_fail_task(2),
        may_fail_task(3),
        return_exceptions=True  # 异常作为结果返回
    )
    
    print(f"结果(含异常): {results}")
    # 结果: ['任务 1 完成', '任务 2 完成', ValueError('任务 3 失败!')]

asyncio.run(main_with_errors())

4.2 asyncio.create_task - 创建任务

python 复制代码
# ===== asyncio.create_task 创建任务 =====

import asyncio
import time

async def long_task(name):
    """长时间运行的任务"""
    print(f"[{name}] 开始")
    await asyncio.sleep(2)
    print(f"[{name}] 结束")
    return f"{name} 结果"

async def main_task():
    """使用 create_task"""
    start = time.time()
    
    # 创建任务(立即开始执行)
    task1 = asyncio.create_task(long_task("任务A"))
    task2 = asyncio.create_task(long_task("任务B"))
    
    print("任务已创建,开始等待...")
    
    # await 等待任务完成
    result1 = await task1
    result2 = await task2
    
    print(f"结果: {result1}, {result2}")
    print(f"总耗时: {time.time() - start:.2f}秒")  # ~2 秒(并发)

asyncio.run(main_task())

print("\n" + "="*50 + "\n")

# ===== Task 状态追踪 =====

async def tracked_task(task_id):
    """带状态追踪的任务"""
    await asyncio.sleep(task_id * 0.5)
    return f"任务 {task_id}"

async def main_track():
    """追踪任务状态"""
    
    # 创建任务
    tasks = [
        asyncio.create_task(tracked_task(i))
        for i in range(1, 4)
    ]
    
    # 等待 0.5 秒后检查状态
    await asyncio.sleep(0.5)
    
    for i, task in enumerate(tasks, 1):
        print(f"任务 {i}: {task.get_name()}, 状态={task.done()}")
    
    # 等待所有任务完成
    results = await asyncio.gather(*tasks)
    print(f"所有任务完成: {results}")

asyncio.run(main_track())

4.3 asyncio.wait - 等待任务组

python 复制代码
# ===== asyncio.wait 等待任务组 =====

import asyncio
from asyncio import FIRST_COMPLETED, FIRST_EXCEPTION

async def task(name, delay):
    """示例任务"""
    await asyncio.sleep(delay)
    return f"{name} 完成"

async def main_wait():
    """使用 asyncio.wait"""
    
    # 创建任务
    tasks = [
        asyncio.create_task(task("快速任务", 0.5)),
        asyncio.create_task(task("中速任务", 1.5)),
        asyncio.create_task(task("慢速任务", 3)),
    ]
    
    # 等待所有任务完成
    done, pending = await asyncio.wait(tasks)
    print(f"完成: {[t.result() for t in done]}")
    
    # 等待第一个任务完成
    tasks = [
        asyncio.create_task(task("任务A", 2)),
        asyncio.create_task(task("任务B", 1)),
        asyncio.create_task(task("任务C", 0.5)),
    ]
    
    done, pending = await asyncio.wait(
        tasks,
        return_when=FIRST_COMPLETED  # 第一个完成时返回
    )
    
    print(f"第一个完成: {[t.result() for t in done]}")
    print(f"仍在运行: {len(pending)} 个")
    
    # 取消未完成的任务
    for t in pending:
        t.cancel()
    await asyncio.gather(*pending, return_exceptions=True)

asyncio.run(main_wait())

print("\n" + "="*50 + "\n")

# ===== asyncio.as_completed - 按完成顺序处理 =====

async def main_as_completed():
    """按完成顺序处理结果"""
    
    tasks = [
        asyncio.create_task(task(f"任务{i}", i * 0.5))
        for i in range(1, 4)
    ]
    
    # 按完成顺序获取结果
    for future in asyncio.as_completed(tasks):
        result = await future
        print(f"完成: {result}")

asyncio.run(main_as_completed())
# 输出顺序:任务3(0.5s) -> 任务2(1s) -> 任务1(1.5s)

五、异步上下文管理器

5.1 async with 异步上下文管理器

python 复制代码
# ===== 异步上下文管理器 =====

import asyncio

class AsyncResource:
    """异步资源管理器"""
    
    async def __aenter__(self):
        """进入上下文"""
        print("获取资源...")
        await asyncio.sleep(0.5)  # 模拟获取连接
        print("资源已获取")
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """退出上下文"""
        print("释放资源...")
        await asyncio.sleep(0.5)  # 模拟释放连接
        print("资源已释放")
        return False  # 不抑制异常

async def main_async_with():
    """使用 async with"""
    async with AsyncResource() as resource:
        print(f"使用资源: {resource}")
        await asyncio.sleep(1)  # 模拟使用资源

asyncio.run(main_async_with())

print("\n" + "="*50 + "\n")

# ===== 异步生成器作为上下文管理器 =====

async def async_context_manager():
    """异步生成器作为上下文管理器"""
    
    async def resource_manager():
        print("获取资源")
        yield "资源句柄"
        print("释放资源")
    
    async with resource_manager() as handle:
        print(f"使用 {handle}")
        await asyncio.sleep(0.5)

asyncio.run(async_context_manager())

5.2 异步迭代器

python 复制代码
# ===== 异步迭代器 =====

class AsyncIterator:
    """异步迭代器"""
    
    def __init__(self, items):
        self.items = items
        self.index = 0
    
    def __aiter__(self):
        """返回异步迭代器本身"""
        return self
    
    async def __anext__(self):
        """获取下一个元素"""
        if self.index >= len(self.items):
            raise StopAsyncIteration
        item = self.items[self.index]
        self.index += 1
        await asyncio.sleep(0.1)  # 模拟异步操作
        return item

async def main_async_iter():
    """使用异步迭代器"""
    async for item in AsyncIterator([1, 2, 3, 4, 5]):
        print(f"处理: {item}")

asyncio.run(main_async_iter())

print("\n" + "="*50 + "\n")

# ===== 异步生成器 =====

async def async_data_generator(n):
    """异步数据生成器"""
    for i in range(n):
        await asyncio.sleep(0.5)  # 模拟数据获取
        yield i  # 生成数据

async def main_async_gen():
    """使用异步生成器"""
    async for data in async_data_generator(5):
        print(f"收到数据: {data}")

asyncio.run(main_async_gen())

六、异步队列

6.1 asyncio.Queue 异步队列

python 复制代码
# ===== asyncio.Queue 异步队列 =====

import asyncio

async def producer(queue, name, count):
    """生产者"""
    for i in range(count):
        item = f"{name}-{i}"
        await queue.put(item)
        print(f"[{name}] 生产: {item}")
        await asyncio.sleep(0.5)
    
    # 发送结束信号
    await queue.put(None)

async def consumer(queue, name):
    """消费者"""
    while True:
        item = await queue.get()
        if item is None:  # 收到结束信号
            queue.task_done()
            break
        print(f"[{name}] 消费: {item}")
        await asyncio.sleep(1)  # 模拟处理
        queue.task_done()

async def main_queue():
    """生产者-消费者模式"""
    queue = asyncio.Queue()
    
    # 创建生产者和消费者
    producers = [
        asyncio.create_task(producer(queue, f"生产者{i}", 3))
        for i in range(2)
    ]
    
    consumers = [
        asyncio.create_task(consumer(queue, f"消费者{i}"))
        for i in range(2)
    ]
    
    # 等待所有生产者完成
    await asyncio.gather(*producers)
    
    # 发送结束信号(消费者数量)
    for _ in consumers:
        await queue.put(None)
    
    # 等待所有消费者完成
    await asyncio.gather(*consumers)

asyncio.run(main_queue())

print("\n" + "="*50 + "\n")

# ===== Queue 的其他特性 =====

async def queue_features():
    """Queue 的高级特性"""
    queue = asyncio.Queue(maxsize=3)  # 设置最大容量
    
    # put_nowait / get_nowait(非阻塞)
    try:
        queue.put_nowait("item1")
        queue.put_nowait("item2")
        queue.put_nowait("item3")
        queue.put_nowait("item4")  # 会抛出 Full
    except asyncio.QueueFull:
        print("队列已满!")
    
    # 获取队列信息
    print(f"队列大小: {queue.qsize()}")
    print(f"队列是否为空: {queue.empty()}")
    print(f"队列是否满: {queue.full()}")
    
    # 阻塞等待
    item = await queue.get()
    print(f"获取: {item}")

asyncio.run(queue_features())

七、实战:异步 HTTP 客户端

7.1 使用 aiohttp

python 复制代码
# ===== aiohttp 异步 HTTP 客户端 =====
# 需要安装:pip install aiohttp

import asyncio
import aiohttp
import time

async def fetch(session, url):
    """获取单个 URL"""
    async with session.get(url) as response:
        return await response.text()

async def fetch_all(urls):
    """并发获取多个 URL"""
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks, return_exceptions=True)
        return results

async def main_aiohttp():
    """aiohttp 实战"""
    urls = [
        "https://httpbin.org/delay/1",
        "https://httpbin.org/delay/2",
        "https://httpbin.org/delay/1",
    ]
    
    start = time.time()
    results = await fetch_all(urls)
    
    print(f"完成 {len(results)} 个请求")
    print(f"总耗时: {time.time() - start:.2f}秒")  # ~2 秒(并发)
    
    for i, result in enumerate(results, 1):
        if isinstance(result, Exception):
            print(f"请求 {i} 失败: {result}")
        else:
            print(f"请求 {i} 成功,长度: {len(result)}")

# asyncio.run(main_aiohttp())  # 取消注释运行

print("\n" + "="*50 + "\n")

# ===== 带重试和超时的 HTTP 请求 =====

from aiohttp import ClientError, ClientTimeout

async def fetch_with_retry(session, url, max_retries=3):
    """带重试的请求"""
    for attempt in range(max_retries):
        try:
            async with session.get(url) as response:
                if response.status == 200:
                    return await response.text()
                else:
                    print(f"状态码 {response.status},重试...")
        except ClientError as e:
            print(f"请求失败(尝试 {attempt+1}/{max_retries}): {e}")
            if attempt < max_retries - 1:
                await asyncio.sleep(2 ** attempt)  # 指数退避
        except asyncio.TimeoutError:
            print(f"超时(尝试 {attempt+1}/{max_retries})")
            if attempt < max_retries - 1:
                await asyncio.sleep(2 ** attempt)
    
    return None

async def main_with_retry():
    """带重试的请求实战"""
    timeout = ClientTimeout(total=10)  # 10 秒超时
    
    async with aiohttp.ClientSession(timeout=timeout) as session:
        url = "https://httpbin.org/delay/2"
        result = await fetch_with_retry(session, url)
        if result:
            print(f"成功获取 {len(result)} 字节")
        else:
            print("请求失败")

# asyncio.run(main_with_retry())  # 取消注释运行

7.2 异步文件操作

python 复制代码
# ===== 异步文件操作 =====
# 需要安装:pip install aiofiles

import asyncio
import aiofiles

async def async_write():
    """异步写入文件"""
    async with aiofiles.open('test.txt', 'w') as f:
        await f.write('Hello, ')
        await f.write('Async World!')
    print("写入完成")

async def async_read():
    """异步读取文件"""
    async with aiofiles.open('test.txt', 'r') as f:
        content = await f.read()
    print(f"读取内容: {content}")
    return content

async def main_file():
    """文件操作实战"""
    await async_write()
    await async_read()

asyncio.run(main_file())

print("\n" + "="*50 + "\n")

# ===== 批量文件处理 =====

async def process_file(filepath):
    """处理单个文件"""
    async with aiofiles.open(filepath, 'r') as f:
        content = await f.read()
    # 模拟处理
    await asyncio.sleep(0.1)
    return len(content)

async def main_batch_files():
    """批量处理文件"""
    # 假设有多个文件
    filepaths = [f'file_{i}.txt' for i in range(10)]
    
    # 创建任务
    tasks = [process_file(fp) for fp in filepaths]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    
    # 统计
    success = sum(1 for r in results if isinstance(r, int))
    print(f"成功处理 {success} 个文件")

# asyncio.run(main_batch_files())  # 取消注释运行

7.3 异步数据库操作

python 复制代码
# ===== 异步数据库操作 =====
# 需要安装:pip install aiomysql / pip install asyncpg / pip install aiosqlite

import asyncio
import aiosqlite  # SQLite 异步驱动

async def main_database():
    """异步数据库操作"""
    
    # 连接数据库
    async with aiosqlite.connect('test.db') as db:
        # 创建表
        await db.execute('''
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY,
                name TEXT,
                email TEXT
            )
        ''')
        await db.commit()
        
        # 插入数据
        await db.execute(
            'INSERT INTO users (name, email) VALUES (?, ?)',
            ('Alice', 'alice@example.com')
        )
        await db.execute(
            'INSERT INTO users (name, email) VALUES (?, ?)',
            ('Bob', 'bob@example.com')
        )
        await db.commit()
        
        # 查询数据
        async with db.execute('SELECT * FROM users') as cursor:
            rows = await cursor.fetchall()
            for row in rows:
                print(f"用户: {row}")
        
        # 事务回滚示例
        try:
            await db.execute('INSERT INTO users VALUES (?, ?, ?)', (1, 'Test', 'test@test.com'))
            await db.commit()
        except Exception as e:
            await db.rollback()
            print(f"回滚: {e}")

asyncio.run(main_database())

八、常见问题与最佳实践

8.1 常见错误

python 复制代码
# ===== 常见错误与解决方案 =====

# ===== 错误 1:在非 async 函数中使用 await =====
def wrong_await():
    # await asyncio.sleep(1)  # ❌ 语法错误
    pass

# ===== 错误 2:忘记 await =====
async def forgot_await():
    result = asyncio.sleep(1)  # ❌ 不会执行!
    print("这里会立即执行")
    # 应该:await asyncio.sleep(1)

# ===== 错误 3:混用同步和异步代码 =====
import time

async def mixed_code():
    """混用同步和异步(不推荐)"""
    # 同步睡眠(阻塞!)
    time.sleep(1)  # ❌ 阻塞整个事件循环
    
    # 异步睡眠(非阻塞)
    await asyncio.sleep(1)  # ✅ 正确
    
    # 同步 I/O(阻塞!)
    # with open('file.txt') as f:  # ❌ 阻塞!
    #     content = f.read()
    
    # 异步 I/O(非阻塞)
    # async with aiofiles.open('file.txt') as f:  # ✅ 正确
    #     content = await f.read()

# ===== 错误 4:死锁 =====
import threading

async def deadlock_example():
    """可能导致死锁的代码"""
    # 在异步代码中使用阻塞的 Lock
    lock = threading.Lock()  # ❌ 不要用 threading.Lock
    
    # 应该用 asyncio.Lock
    async_lock = asyncio.Lock()
    
    async with async_lock:
        await asyncio.sleep(1)
        print("锁释放")

# ===== 错误 5:异常未捕获 =====
async def unhandled_exception():
    """未处理的异常"""
    async def may_fail():
        raise ValueError("Oops!")
    
    try:
        await may_fail()
    except ValueError as e:
        print(f"捕获异常: {e}")

asyncio.run(unhandled_exception())

8.2 性能优化技巧

python 复制代码
# ===== 性能优化技巧 =====

import asyncio
import time

# ===== 技巧 1:批量并发 =====
async def batch_concurrent():
    """批量并发(限制并发数)"""
    
    async def fetch(url):
        await asyncio.sleep(0.5)
        return f"响应: {url}"
    
    urls = [f"url_{i}" for i in range(100)]
    
    # 限制并发数为 10
    semaphore = asyncio.Semaphore(10)
    
    async def bounded_fetch(url):
        async with semaphore:
            return await fetch(url)
    
    start = time.time()
    results = await asyncio.gather(*[bounded_fetch(url) for url in urls])
    print(f"100 个请求,并发限制 10,耗时: {time.time() - start:.2f}秒")

asyncio.run(batch_concurrent())

print("\n" + "="*50 + "\n")

# ===== 技巧 2:使用 asyncio.create_task 提前启动 =====
async def early_task_start():
    """提前启动任务"""
    
    async def slow_task():
        await asyncio.sleep(2)
        return "完成"
    
    start = time.time()
    
    # 方式 1:顺序执行
    # result1 = await slow_task()
    # result2 = await slow_task()
    # 耗时:4 秒
    
    # 方式 2:提前启动任务
    task = asyncio.create_task(slow_task())  # 立即开始
    await asyncio.sleep(0.5)  # 做其他事
    result = await task
    print(f"提前启动,耗时: {time.time() - start:.2f}秒")

asyncio.run(early_task_start())

print("\n" + "="*50 + "\n")

# ===== 技巧 3:取消任务 =====
async def cancellable_task():
    """可取消的任务"""
    
    async def long_running():
        try:
            for i in range(10):
                print(f"处理 {i}/10")
                await asyncio.sleep(1)
            return "完成"
        except asyncio.CancelledError:
            print("任务被取消")
            raise
    
    task = asyncio.create_task(long_running())
    
    # 3 秒后取消
    await asyncio.sleep(3)
    task.cancel()
    
    try:
        await task
    except asyncio.CancelledError:
        print("任务已取消")

asyncio.run(cancellable_task())

8.3 最佳实践清单

#mermaid-svg-WikLhqrUQ2DlWcPX{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WikLhqrUQ2DlWcPX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WikLhqrUQ2DlWcPX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WikLhqrUQ2DlWcPX .error-icon{fill:#552222;}#mermaid-svg-WikLhqrUQ2DlWcPX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WikLhqrUQ2DlWcPX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WikLhqrUQ2DlWcPX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WikLhqrUQ2DlWcPX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WikLhqrUQ2DlWcPX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WikLhqrUQ2DlWcPX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WikLhqrUQ2DlWcPX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WikLhqrUQ2DlWcPX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WikLhqrUQ2DlWcPX .marker.cross{stroke:#333333;}#mermaid-svg-WikLhqrUQ2DlWcPX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WikLhqrUQ2DlWcPX p{margin:0;}#mermaid-svg-WikLhqrUQ2DlWcPX .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WikLhqrUQ2DlWcPX .cluster-label text{fill:#333;}#mermaid-svg-WikLhqrUQ2DlWcPX .cluster-label span{color:#333;}#mermaid-svg-WikLhqrUQ2DlWcPX .cluster-label span p{background-color:transparent;}#mermaid-svg-WikLhqrUQ2DlWcPX .label text,#mermaid-svg-WikLhqrUQ2DlWcPX span{fill:#333;color:#333;}#mermaid-svg-WikLhqrUQ2DlWcPX .node rect,#mermaid-svg-WikLhqrUQ2DlWcPX .node circle,#mermaid-svg-WikLhqrUQ2DlWcPX .node ellipse,#mermaid-svg-WikLhqrUQ2DlWcPX .node polygon,#mermaid-svg-WikLhqrUQ2DlWcPX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WikLhqrUQ2DlWcPX .rough-node .label text,#mermaid-svg-WikLhqrUQ2DlWcPX .node .label text,#mermaid-svg-WikLhqrUQ2DlWcPX .image-shape .label,#mermaid-svg-WikLhqrUQ2DlWcPX .icon-shape .label{text-anchor:middle;}#mermaid-svg-WikLhqrUQ2DlWcPX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WikLhqrUQ2DlWcPX .rough-node .label,#mermaid-svg-WikLhqrUQ2DlWcPX .node .label,#mermaid-svg-WikLhqrUQ2DlWcPX .image-shape .label,#mermaid-svg-WikLhqrUQ2DlWcPX .icon-shape .label{text-align:center;}#mermaid-svg-WikLhqrUQ2DlWcPX .node.clickable{cursor:pointer;}#mermaid-svg-WikLhqrUQ2DlWcPX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WikLhqrUQ2DlWcPX .arrowheadPath{fill:#333333;}#mermaid-svg-WikLhqrUQ2DlWcPX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WikLhqrUQ2DlWcPX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WikLhqrUQ2DlWcPX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WikLhqrUQ2DlWcPX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WikLhqrUQ2DlWcPX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WikLhqrUQ2DlWcPX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WikLhqrUQ2DlWcPX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WikLhqrUQ2DlWcPX .cluster text{fill:#333;}#mermaid-svg-WikLhqrUQ2DlWcPX .cluster span{color:#333;}#mermaid-svg-WikLhqrUQ2DlWcPX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-WikLhqrUQ2DlWcPX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WikLhqrUQ2DlWcPX rect.text{fill:none;stroke-width:0;}#mermaid-svg-WikLhqrUQ2DlWcPX .icon-shape,#mermaid-svg-WikLhqrUQ2DlWcPX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WikLhqrUQ2DlWcPX .icon-shape p,#mermaid-svg-WikLhqrUQ2DlWcPX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WikLhqrUQ2DlWcPX .icon-shape .label rect,#mermaid-svg-WikLhqrUQ2DlWcPX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WikLhqrUQ2DlWcPX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WikLhqrUQ2DlWcPX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WikLhqrUQ2DlWcPX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 异步编程最佳实践
基础规范
性能优化
错误处理
调试技巧
✅ 使用 asyncio.run() 启动
✅ await 只能在 async 函数中
✅ 避免同步阻塞调用
✅ 使用 Semaphore 限制并发
✅ 提前 create_task
✅ 批量处理
✅ 捕获 CancelledError
✅ 超时处理
✅ 重试机制
✅ 添加日志
✅ 使用 asyncio.current_task()
✅ traceback 打印


九、实战案例

9.1 异步爬虫

python 复制代码
# ===== 异步爬虫实战 =====
# pip install aiohttp beautifulsoup4

import asyncio
import aiohttp
from bs4 import BeautifulSoup
import time

class AsyncSpider:
    """异步爬虫"""
    
    def __init__(self, concurrency=10):
        self.concurrency = concurrency
        self.semaphore = asyncio.Semaphore(concurrency)
        self.results = []
    
    async def fetch(self, session, url):
        """抓取单个页面"""
        async with self.semaphore:
            try:
                async with session.get(url, timeout=aiohttp.ClientTimeout(total=10)) as response:
                    if response.status == 200:
                        html = await response.text()
                        return html
                    return None
            except Exception as e:
                print(f"抓取失败 {url}: {e}")
                return None
    
    async def parse(self, html):
        """解析页面"""
        if not html:
            return []
        
        soup = BeautifulSoup(html, 'html.parser')
        # 提取标题
        titles = [tag.get_text() for tag in soup.find_all('h2')]
        return titles
    
    async def crawl(self, urls):
        """爬取多个页面"""
        async with aiohttp.ClientSession() as session:
            tasks = [self.fetch(session, url) for url in urls]
            htmls = await asyncio.gather(*tasks, return_exceptions=True)
            
            # 解析所有页面
            all_titles = []
            for html in htmls:
                if isinstance(html, str):
                    titles = await self.parse(html)
                    all_titles.extend(titles)
            
            return all_titles

async def main_spider():
    """爬虫主函数"""
    spider = AsyncSpider(concurrency=5)
    
    urls = [
        f"https://example.com/page{i}"
        for i in range(10)
    ]
    
    start = time.time()
    titles = await spider.crawl(urls)
    print(f"抓取 {len(titles)} 个标题")
    print(f"耗时: {time.time() - start:.2f}秒")

# asyncio.run(main_spider())  # 取消注释运行

9.2 异步 API 服务

python 复制代码
# ===== 异步 API 服务 =====
# pip install fastapi uvicorn

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import asyncio

app = FastAPI()

# 模拟数据库
items = {}

class Item(BaseModel):
    name: str
    description: str = None
    price: float

@app.post("/items/")
async def create_item(item: Item):
    """创建项目"""
    await asyncio.sleep(0.1)  # 模拟数据库操作
    items[item.name] = item
    return item

@app.get("/items/{item_name}")
async def get_item(item_name: str):
    """获取项目"""
    await asyncio.sleep(0.1)
    if item_name not in items:
        raise HTTPException(status_code=404, detail="Item not found")
    return items[item_name]

@app.get("/items/")
async def list_items():
    """列出所有项目"""
    await asyncio.sleep(0.1)
    return list(items.values())

# 运行:uvicorn main:app --reload

9.3 异步定时任务

python 复制代码
# ===== 异步定时任务 =====

import asyncio
from datetime import datetime

class AsyncScheduler:
    """简单的异步调度器"""
    
    def __init__(self):
        self.tasks = []
    
    async def periodic_task(self, interval, func, *args, **kwargs):
        """定期执行任务"""
        while True:
            try:
                await func(*args, **kwargs)
            except Exception as e:
                print(f"任务执行失败: {e}")
            
            await asyncio.sleep(interval)
    
    def schedule(self, interval, func, *args, **kwargs):
        """调度定期任务"""
        task = asyncio.create_task(
            self.periodic_task(interval, func, *args, **kwargs)
        )
        self.tasks.append(task)
        return task
    
    async def run(self):
        """运行调度器"""
        await asyncio.gather(*self.tasks)

# 使用示例
async def print_time():
    print(f"当前时间: {datetime.now().strftime('%H:%M:%S')}")

async def main_scheduler():
    scheduler = AsyncScheduler()
    
    # 每 3 秒执行一次
    scheduler.schedule(3, print_time)
    
    # 10 秒后停止
    await asyncio.sleep(10)
    
    # 取消所有任务
    for task in scheduler.tasks:
        task.cancel()
    await asyncio.gather(*scheduler.tasks, return_exceptions=True)

# asyncio.run(main_scheduler())  # 取消注释运行

十、总结

10.1 知识体系总结

#mermaid-svg-T2dMuXfDxkbssHdC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-T2dMuXfDxkbssHdC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-T2dMuXfDxkbssHdC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-T2dMuXfDxkbssHdC .error-icon{fill:#552222;}#mermaid-svg-T2dMuXfDxkbssHdC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-T2dMuXfDxkbssHdC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-T2dMuXfDxkbssHdC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-T2dMuXfDxkbssHdC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-T2dMuXfDxkbssHdC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-T2dMuXfDxkbssHdC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-T2dMuXfDxkbssHdC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-T2dMuXfDxkbssHdC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-T2dMuXfDxkbssHdC .marker.cross{stroke:#333333;}#mermaid-svg-T2dMuXfDxkbssHdC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-T2dMuXfDxkbssHdC p{margin:0;}#mermaid-svg-T2dMuXfDxkbssHdC .edge{stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .section--1 rect,#mermaid-svg-T2dMuXfDxkbssHdC .section--1 path,#mermaid-svg-T2dMuXfDxkbssHdC .section--1 circle,#mermaid-svg-T2dMuXfDxkbssHdC .section--1 polygon,#mermaid-svg-T2dMuXfDxkbssHdC .section--1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .section--1 text{fill:#ffffff;}#mermaid-svg-T2dMuXfDxkbssHdC .node-icon--1{font-size:40px;color:#ffffff;}#mermaid-svg-T2dMuXfDxkbssHdC .section-edge--1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .edge-depth--1{stroke-width:17;}#mermaid-svg-T2dMuXfDxkbssHdC .section--1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled,#mermaid-svg-T2dMuXfDxkbssHdC .disabled circle,#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:lightgray;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:#efefef;}#mermaid-svg-T2dMuXfDxkbssHdC .section-0 rect,#mermaid-svg-T2dMuXfDxkbssHdC .section-0 path,#mermaid-svg-T2dMuXfDxkbssHdC .section-0 circle,#mermaid-svg-T2dMuXfDxkbssHdC .section-0 polygon,#mermaid-svg-T2dMuXfDxkbssHdC .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-T2dMuXfDxkbssHdC .section-0 text{fill:black;}#mermaid-svg-T2dMuXfDxkbssHdC .node-icon-0{font-size:40px;color:black;}#mermaid-svg-T2dMuXfDxkbssHdC .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-T2dMuXfDxkbssHdC .edge-depth-0{stroke-width:14;}#mermaid-svg-T2dMuXfDxkbssHdC .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled,#mermaid-svg-T2dMuXfDxkbssHdC .disabled circle,#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:lightgray;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:#efefef;}#mermaid-svg-T2dMuXfDxkbssHdC .section-1 rect,#mermaid-svg-T2dMuXfDxkbssHdC .section-1 path,#mermaid-svg-T2dMuXfDxkbssHdC .section-1 circle,#mermaid-svg-T2dMuXfDxkbssHdC .section-1 polygon,#mermaid-svg-T2dMuXfDxkbssHdC .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .section-1 text{fill:black;}#mermaid-svg-T2dMuXfDxkbssHdC .node-icon-1{font-size:40px;color:black;}#mermaid-svg-T2dMuXfDxkbssHdC .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .edge-depth-1{stroke-width:11;}#mermaid-svg-T2dMuXfDxkbssHdC .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled,#mermaid-svg-T2dMuXfDxkbssHdC .disabled circle,#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:lightgray;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:#efefef;}#mermaid-svg-T2dMuXfDxkbssHdC .section-2 rect,#mermaid-svg-T2dMuXfDxkbssHdC .section-2 path,#mermaid-svg-T2dMuXfDxkbssHdC .section-2 circle,#mermaid-svg-T2dMuXfDxkbssHdC .section-2 polygon,#mermaid-svg-T2dMuXfDxkbssHdC .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .section-2 text{fill:#ffffff;}#mermaid-svg-T2dMuXfDxkbssHdC .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-T2dMuXfDxkbssHdC .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .edge-depth-2{stroke-width:8;}#mermaid-svg-T2dMuXfDxkbssHdC .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled,#mermaid-svg-T2dMuXfDxkbssHdC .disabled circle,#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:lightgray;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:#efefef;}#mermaid-svg-T2dMuXfDxkbssHdC .section-3 rect,#mermaid-svg-T2dMuXfDxkbssHdC .section-3 path,#mermaid-svg-T2dMuXfDxkbssHdC .section-3 circle,#mermaid-svg-T2dMuXfDxkbssHdC .section-3 polygon,#mermaid-svg-T2dMuXfDxkbssHdC .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .section-3 text{fill:black;}#mermaid-svg-T2dMuXfDxkbssHdC .node-icon-3{font-size:40px;color:black;}#mermaid-svg-T2dMuXfDxkbssHdC .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .edge-depth-3{stroke-width:5;}#mermaid-svg-T2dMuXfDxkbssHdC .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled,#mermaid-svg-T2dMuXfDxkbssHdC .disabled circle,#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:lightgray;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:#efefef;}#mermaid-svg-T2dMuXfDxkbssHdC .section-4 rect,#mermaid-svg-T2dMuXfDxkbssHdC .section-4 path,#mermaid-svg-T2dMuXfDxkbssHdC .section-4 circle,#mermaid-svg-T2dMuXfDxkbssHdC .section-4 polygon,#mermaid-svg-T2dMuXfDxkbssHdC .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .section-4 text{fill:black;}#mermaid-svg-T2dMuXfDxkbssHdC .node-icon-4{font-size:40px;color:black;}#mermaid-svg-T2dMuXfDxkbssHdC .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .edge-depth-4{stroke-width:2;}#mermaid-svg-T2dMuXfDxkbssHdC .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled,#mermaid-svg-T2dMuXfDxkbssHdC .disabled circle,#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:lightgray;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:#efefef;}#mermaid-svg-T2dMuXfDxkbssHdC .section-5 rect,#mermaid-svg-T2dMuXfDxkbssHdC .section-5 path,#mermaid-svg-T2dMuXfDxkbssHdC .section-5 circle,#mermaid-svg-T2dMuXfDxkbssHdC .section-5 polygon,#mermaid-svg-T2dMuXfDxkbssHdC .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .section-5 text{fill:black;}#mermaid-svg-T2dMuXfDxkbssHdC .node-icon-5{font-size:40px;color:black;}#mermaid-svg-T2dMuXfDxkbssHdC .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .edge-depth-5{stroke-width:-1;}#mermaid-svg-T2dMuXfDxkbssHdC .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled,#mermaid-svg-T2dMuXfDxkbssHdC .disabled circle,#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:lightgray;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:#efefef;}#mermaid-svg-T2dMuXfDxkbssHdC .section-6 rect,#mermaid-svg-T2dMuXfDxkbssHdC .section-6 path,#mermaid-svg-T2dMuXfDxkbssHdC .section-6 circle,#mermaid-svg-T2dMuXfDxkbssHdC .section-6 polygon,#mermaid-svg-T2dMuXfDxkbssHdC .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .section-6 text{fill:black;}#mermaid-svg-T2dMuXfDxkbssHdC .node-icon-6{font-size:40px;color:black;}#mermaid-svg-T2dMuXfDxkbssHdC .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .edge-depth-6{stroke-width:-4;}#mermaid-svg-T2dMuXfDxkbssHdC .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled,#mermaid-svg-T2dMuXfDxkbssHdC .disabled circle,#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:lightgray;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:#efefef;}#mermaid-svg-T2dMuXfDxkbssHdC .section-7 rect,#mermaid-svg-T2dMuXfDxkbssHdC .section-7 path,#mermaid-svg-T2dMuXfDxkbssHdC .section-7 circle,#mermaid-svg-T2dMuXfDxkbssHdC .section-7 polygon,#mermaid-svg-T2dMuXfDxkbssHdC .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .section-7 text{fill:black;}#mermaid-svg-T2dMuXfDxkbssHdC .node-icon-7{font-size:40px;color:black;}#mermaid-svg-T2dMuXfDxkbssHdC .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .edge-depth-7{stroke-width:-7;}#mermaid-svg-T2dMuXfDxkbssHdC .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled,#mermaid-svg-T2dMuXfDxkbssHdC .disabled circle,#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:lightgray;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:#efefef;}#mermaid-svg-T2dMuXfDxkbssHdC .section-8 rect,#mermaid-svg-T2dMuXfDxkbssHdC .section-8 path,#mermaid-svg-T2dMuXfDxkbssHdC .section-8 circle,#mermaid-svg-T2dMuXfDxkbssHdC .section-8 polygon,#mermaid-svg-T2dMuXfDxkbssHdC .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .section-8 text{fill:black;}#mermaid-svg-T2dMuXfDxkbssHdC .node-icon-8{font-size:40px;color:black;}#mermaid-svg-T2dMuXfDxkbssHdC .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .edge-depth-8{stroke-width:-10;}#mermaid-svg-T2dMuXfDxkbssHdC .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled,#mermaid-svg-T2dMuXfDxkbssHdC .disabled circle,#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:lightgray;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:#efefef;}#mermaid-svg-T2dMuXfDxkbssHdC .section-9 rect,#mermaid-svg-T2dMuXfDxkbssHdC .section-9 path,#mermaid-svg-T2dMuXfDxkbssHdC .section-9 circle,#mermaid-svg-T2dMuXfDxkbssHdC .section-9 polygon,#mermaid-svg-T2dMuXfDxkbssHdC .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .section-9 text{fill:black;}#mermaid-svg-T2dMuXfDxkbssHdC .node-icon-9{font-size:40px;color:black;}#mermaid-svg-T2dMuXfDxkbssHdC .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .edge-depth-9{stroke-width:-13;}#mermaid-svg-T2dMuXfDxkbssHdC .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled,#mermaid-svg-T2dMuXfDxkbssHdC .disabled circle,#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:lightgray;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:#efefef;}#mermaid-svg-T2dMuXfDxkbssHdC .section-10 rect,#mermaid-svg-T2dMuXfDxkbssHdC .section-10 path,#mermaid-svg-T2dMuXfDxkbssHdC .section-10 circle,#mermaid-svg-T2dMuXfDxkbssHdC .section-10 polygon,#mermaid-svg-T2dMuXfDxkbssHdC .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .section-10 text{fill:black;}#mermaid-svg-T2dMuXfDxkbssHdC .node-icon-10{font-size:40px;color:black;}#mermaid-svg-T2dMuXfDxkbssHdC .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .edge-depth-10{stroke-width:-16;}#mermaid-svg-T2dMuXfDxkbssHdC .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled,#mermaid-svg-T2dMuXfDxkbssHdC .disabled circle,#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:lightgray;}#mermaid-svg-T2dMuXfDxkbssHdC .disabled text{fill:#efefef;}#mermaid-svg-T2dMuXfDxkbssHdC .section-root rect,#mermaid-svg-T2dMuXfDxkbssHdC .section-root path,#mermaid-svg-T2dMuXfDxkbssHdC .section-root circle,#mermaid-svg-T2dMuXfDxkbssHdC .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-T2dMuXfDxkbssHdC .section-root text{fill:#ffffff;}#mermaid-svg-T2dMuXfDxkbssHdC .section-root span{color:#ffffff;}#mermaid-svg-T2dMuXfDxkbssHdC .section-2 span{color:#ffffff;}#mermaid-svg-T2dMuXfDxkbssHdC .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-T2dMuXfDxkbssHdC .edge{fill:none;}#mermaid-svg-T2dMuXfDxkbssHdC .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-T2dMuXfDxkbssHdC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Python

异步编程
基础语法
async def
await
协程对象
事件循环
get_running_loop
run_until_complete
create_task
并发任务
gather
wait
as_completed
create_task
异步工具
Queue
Semaphore
Lock
Event
异步生态
aiohttp
aiofiles
aiomysql
FastAPI
最佳实践
避免阻塞
限制并发
错误处理
超时控制

10.2 学习路线图

#mermaid-svg-EKHyTKkVTFNt39en{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-EKHyTKkVTFNt39en .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EKHyTKkVTFNt39en .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EKHyTKkVTFNt39en .error-icon{fill:#552222;}#mermaid-svg-EKHyTKkVTFNt39en .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EKHyTKkVTFNt39en .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EKHyTKkVTFNt39en .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EKHyTKkVTFNt39en .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EKHyTKkVTFNt39en .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EKHyTKkVTFNt39en .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EKHyTKkVTFNt39en .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EKHyTKkVTFNt39en .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EKHyTKkVTFNt39en .marker.cross{stroke:#333333;}#mermaid-svg-EKHyTKkVTFNt39en svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EKHyTKkVTFNt39en p{margin:0;}#mermaid-svg-EKHyTKkVTFNt39en .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-EKHyTKkVTFNt39en .cluster-label text{fill:#333;}#mermaid-svg-EKHyTKkVTFNt39en .cluster-label span{color:#333;}#mermaid-svg-EKHyTKkVTFNt39en .cluster-label span p{background-color:transparent;}#mermaid-svg-EKHyTKkVTFNt39en .label text,#mermaid-svg-EKHyTKkVTFNt39en span{fill:#333;color:#333;}#mermaid-svg-EKHyTKkVTFNt39en .node rect,#mermaid-svg-EKHyTKkVTFNt39en .node circle,#mermaid-svg-EKHyTKkVTFNt39en .node ellipse,#mermaid-svg-EKHyTKkVTFNt39en .node polygon,#mermaid-svg-EKHyTKkVTFNt39en .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-EKHyTKkVTFNt39en .rough-node .label text,#mermaid-svg-EKHyTKkVTFNt39en .node .label text,#mermaid-svg-EKHyTKkVTFNt39en .image-shape .label,#mermaid-svg-EKHyTKkVTFNt39en .icon-shape .label{text-anchor:middle;}#mermaid-svg-EKHyTKkVTFNt39en .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-EKHyTKkVTFNt39en .rough-node .label,#mermaid-svg-EKHyTKkVTFNt39en .node .label,#mermaid-svg-EKHyTKkVTFNt39en .image-shape .label,#mermaid-svg-EKHyTKkVTFNt39en .icon-shape .label{text-align:center;}#mermaid-svg-EKHyTKkVTFNt39en .node.clickable{cursor:pointer;}#mermaid-svg-EKHyTKkVTFNt39en .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-EKHyTKkVTFNt39en .arrowheadPath{fill:#333333;}#mermaid-svg-EKHyTKkVTFNt39en .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-EKHyTKkVTFNt39en .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-EKHyTKkVTFNt39en .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EKHyTKkVTFNt39en .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-EKHyTKkVTFNt39en .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EKHyTKkVTFNt39en .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-EKHyTKkVTFNt39en .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-EKHyTKkVTFNt39en .cluster text{fill:#333;}#mermaid-svg-EKHyTKkVTFNt39en .cluster span{color:#333;}#mermaid-svg-EKHyTKkVTFNt39en div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-EKHyTKkVTFNt39en .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-EKHyTKkVTFNt39en rect.text{fill:none;stroke-width:0;}#mermaid-svg-EKHyTKkVTFNt39en .icon-shape,#mermaid-svg-EKHyTKkVTFNt39en .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EKHyTKkVTFNt39en .icon-shape p,#mermaid-svg-EKHyTKkVTFNt39en .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-EKHyTKkVTFNt39en .icon-shape .label rect,#mermaid-svg-EKHyTKkVTFNt39en .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EKHyTKkVTFNt39en .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-EKHyTKkVTFNt39en .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-EKHyTKkVTFNt39en :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 入门
基础
进阶
精通
• 理解同步 vs 异步
• async/await 语法
• 运行第一个协程
• 事件循环原理
• gather 并发执行
• 异步上下文管理器
• Queue/Semaphore
• aiohttp/aiofiles
• 性能优化技巧
• 异步框架开发
• 自定义异步库
• 生产环境部署

10.3 推荐资源

类型 资源 说明
官方文档 asyncio --- 异步 I/O https://docs.python.org/3/library/asyncio.html
官方文档 异步编程指引 https://docs.python.org/3/library/asyncio-dev-guide.html
书籍 《Fluent Python》 深入讲解异步编程
课程 Real Python - Async 免费教程
工具 py-spy 异步代码性能分析
工具 uvloop 高性能事件循环

附录:常用 API 速查

A. 核心函数

python 复制代码
# asyncio.run() - 运行协程
asyncio.run(coro())

# asyncio.create_task() - 创建任务
task = asyncio.create_task(coro())

# asyncio.gather() - 并发执行
results = await asyncio.gather(*coros)

# asyncio.wait() - 等待任务
done, pending = await asyncio.wait(tasks)

# asyncio.sleep() - 异步睡眠
await asyncio.sleep(seconds)

# asyncio.current_task() - 获取当前任务
task = asyncio.current_task()

# asyncio.all_tasks() - 获取所有任务
tasks = asyncio.all_tasks()

B. 队列和锁

python 复制代码
# Queue
queue = asyncio.Queue()
await queue.put(item)
item = await queue.get()
queue.task_done()
await queue.join()

# Semaphore(限流)
semaphore = asyncio.Semaphore(10)
async with semaphore:
    await do_something()

# Lock(异步锁)
lock = asyncio.Lock()
async with lock:
    await do_something()

# Event(事件)
event = asyncio.Event()
event.set()
await event.wait()

# Condition(条件)
condition = asyncio.Condition()
async with condition:
    await condition.wait()
    condition.notify()

本文基于 Python 3.10+ 编写。如有问题欢迎评论区讨论!

相关推荐
Yang96111 小时前
宽温大功率输出,LDMN-GM7 助力矿区雷达性能验收工作
网络·能源
咋吃都不胖lyh1 小时前
LangGraph标准构建示例
开发语言·python
网安小白的进阶之路2 小时前
B模块 安全通信网络 第二门课IPv6与WLAN 03
网络·安全
宸津-代码粉碎机2 小时前
Spring AI企业级Agent实战|多工具自动规划+并行调度落地,彻底解决复杂业务AI任务编排问题
java·大数据·人工智能·spring boot·python·spring
*neverGiveUp*2 小时前
Python基础语法
开发语言·python
dong__csdn2 小时前
websocket实现简单的单聊、群聊demo
网络·websocket·网络协议
一只小鱼儿吖2 小时前
代理IP与内网穿透:网络世界的“隐形斗篷”与“任意门”
网络
天行健,君子而铎2 小时前
自适应、全链路与智能识别——政务数据安全泛监测系统
java·网络·政务
Marst Code2 小时前
[特殊字符] 五大 Workflow 模式详解
人工智能·python