python协程是单线程内可暂停恢复的执行单元,asyncio通过事件循环和await让出控制权实现高并发i/o;需用async def定义、asyncio.run()启动,不可在协程中嵌套调用run,适合i/o密集型任务。

Python协程不是线程,也不是进程,而是一种单线程内可暂停、可恢复的执行单元;asyncio 是 Python 官方提供的异步 I/O 框架,用来编写并发协程程序——它不靠多核,而是靠“让出控制权”来高效处理大量 I/O 等待任务。
async/await 是协程的语法核心
定义协程函数必须用 async def,调用后返回一个协程对象(coroutine object),不会立即执行;真正运行要靠事件循环驱动。await 只能在 async 函数内部使用,且只能等待 awaitable 对象(如协程、Future、带 __await__ 方法的对象)。
- 错误写法:print(my_coro()) —— 这只是创建协程对象,没运行
- 正确启动:await my_coro()(在 async 函数里)或 asyncio.run(my_coro())(顶层入口)
- await 不是“等待完成”,而是“挂起当前协程,把控制权交还给事件循环”,等被 await 的对象就绪后再恢复
事件循环是 asyncio 的心脏
asyncio.run() 会自动创建并运行一个事件循环,执行传入的协程直到结束;你也可以手动获取和管理循环(比如在已运行的线程中复用),但绝大多数入门场景用 asyncio.run() 就够了。
- 同一时间只能有一个事件循环在运行(主线程默认只有一个)
- 不能在协程里调用 asyncio.run() —— 会报 “RuntimeError: asyncio.run() cannot be called from a running event loop”
- 想并发执行多个协程?用 await asyncio.gather(coro1(), coro2(), coro3())
协程适合 I/O 密集型,不是 CPU 密集型
asyncio 解决的是“等”的问题:比如发 HTTP 请求、读文件、连数据库……这些操作实际耗时大多花在等待网络/磁盘响应上。协程在此期间让出控制权,让其他任务运行,从而提升吞吐量。
Perl 基础入门中文教程,chm格式,讲述PERL概述、简单变量、操作符、列表和数组变量、文件读写、模式匹配、控制结构、子程序、关联数组/哈希表、格式化输出、文件系统、引用、面向对象、包和模块等知识点。适合初学者阅读和了解Perl脚本语言。
立即学习“Python免费学习笔记(深入)”;
- 如果写了个纯计算函数(比如算斐波那契第10000项),用 async/await 不但没提速,反而更慢
- 阻塞式调用(如 time.sleep()、requests.get())会卡住整个事件循环;要用 await asyncio.sleep() 或异步库(如 aiohttp 替代 requests)
- 实在要跑 CPU 任务?用 loop.run_in_executor() 丢到线程池/进程池里执行,避免阻塞
一个最小可用例子
下面代码并发请求两个网页(需安装 aiohttp):
import asyncio
import aiohttp
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
task1 = fetch(session, 'https://httpbin.org/delay/1')
task2 = fetch(session, 'https://httpbin.org/delay/1')
html1, html2 = await asyncio.gather(task1, task2)
print(len(html1), len(html2))
asyncio.run(main())
两个请求真正并发执行,总耗时约 1 秒,而非串行的 2 秒——这就是协程的价值所在。








