Python 异步编程(Asynchronous Programming) 的核心语法部分,是 Python3.5+ 的重要特性之一,涉及:

协程(coroutine)机制:async def / await / async for / async with

同步 vs 异步

同步(Synchronous)

代码 逐行执行,一行没结束前下一行不会开始:

1
2
3
4
5
6
7
8
9
10
11
def fetch_data():
time.sleep(3) # 阻塞3秒
return "data"

def main():
print("Start")
data = fetch_data()
print("Got:", data)
print("End")

main()

执行顺序固定:Start → 等3秒 → Got: data → End

异步(Asynchronous)

异步程序 允许挂起等待任务完成,在等待期间可以执行其他任务。

这不是多线程,而是 单线程并发 —— 通过事件循环(event loop)管理任务切换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import asyncio

async def fetch_data():
print("Fetching...")
await asyncio.sleep(3) # 挂起,不阻塞线程
return "data"

async def main():
print("Start")
result = await fetch_data()
print("Got:", result)
print("End")

asyncio.run(main())

输出:

1
2
3
4
Start
Fetching...
Got: data
End

await asyncio.sleep(3) 会“让出控制权”给事件循环,不阻塞整个程序。

协程机制

协程(coroutine)是一种可以暂停和恢复执行的函数,是生成器机制的升级版。

对比传统函数:

类型 关键字 可暂停 可恢复执行 示例
普通函数 def 返回值
生成器 def + yield 生成器对象
协程 async def + await 协程对象

async def:定义协程函数

1
2
async def my_coroutine():
return 42

调用时不会立即执行:

1
2
3
result = my_coroutine()
print(result)
# <coroutine object my_coroutine at 0x...>

这是一个 协程对象(coroutine object),必须通过事件循环运行:

1
2
import asyncio
asyncio.run(my_coroutine()) # 输出 42

await:等待另一个协程的结果

await 关键字只能在 async def 函数中使用。

作用:

暂停当前协程的执行,等待另一个协程或异步任务完成后再恢复。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import asyncio

async def step1():
print("Step 1 start")
await asyncio.sleep(1)
print("Step 1 done")
return "A"

async def step2():
print("Step 2 start")
await asyncio.sleep(2)
print("Step 2 done")
return "B"

async def main():
r1 = await step1()
r2 = await step2()
print(r1, r2)

asyncio.run(main())

执行顺序:

1
2
3
4
5
6
7
Step 1 start
(等待1秒)
Step 1 done
Step 2 start
(等待2秒)
Step 2 done
A B

await 会挂起当前协程,让事件循环有机会去运行其他协程。

asyncio.gather():并发运行

要同时执行多个协程,也即并发,使用:

1
2
3
async def main():
results = await asyncio.gather(step1(), step2())
print(results)

执行时间 ≈ 2 秒(取最长的 sleep),因为两任务同时运行

async for:异步迭代器

用于在异步环境中遍历“异步可迭代对象”,如异步数据流、网络流。

异步迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
class AsyncCounter:
def __init__(self):
self.count = 0

def __aiter__(self):
return self

async def __anext__(self):
if self.count >= 3:
raise StopAsyncIteration
await asyncio.sleep(1) # 模拟异步操作
self.count += 1
return self.count

使用异步 for

1
2
3
4
5
async def main():
async for num in AsyncCounter():
print(num)

asyncio.run(main())

输出:

1
2
3
1
2
3

async with:异步上下文管理器

用于管理需要异步初始化和清理的资源,例如异步锁、异步文件、数据库连接。

定义示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class AsyncContext:
async def __aenter__(self):
print("Entering...")
await asyncio.sleep(1)
return "resource"

async def __aexit__(self, exc_type, exc, tb):
print("Exiting...")
await asyncio.sleep(1)

async def main():
async with AsyncContext() as res:
print("Using:", res)

asyncio.run(main())

输出:

1
2
3
Entering...
Using: resource
Exiting...

关键字总结

关键字 用途 位置 示例
async def 定义协程函数 函数定义时 async def f(): ...
await 等待异步操作结果 协程函数内部 await asyncio.sleep(1)
async for 异步迭代 协程函数内部 async for x in async_iter:
async with 异步上下文管理 协程函数内部 async with lock:

事件循环

事件循环(Event Loop)是协程运行的“调度核心”,它不断地从任务队列中取出准备就绪的协程来执行。

简化示意:

1
2
3
4
5
[task1] -> await I/O -> 暂停
[task2] -> 就绪 -> 执行
[task3] -> await 网络 -> 暂停

任务就绪时自动恢复执行

asyncio 中:

1
asyncio.run(main())  # 自动创建事件循环

或手动管理:

1
2
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

实战示例

并发请求网页示例,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import asyncio
import aiohttp

async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
print(f"{url}: {resp.status}")
return await resp.text()

async def main():
urls = [
"https://example.com",
"https://python.org",
"https://github.com"
]
results = await asyncio.gather(*(fetch(u) for u in urls))
print("Fetched", len(results), "pages")

asyncio.run(main())

三个请求几乎同时发出,速度远快于同步请求。

总结表

机制 关键字 功能 类似同步语法 是否可并发
定义协程 async def 定义可暂停函数 def
挂起等待 await 等待异步操作 调用普通函数
异步迭代 async for 遍历异步对象 for
异步上下文 async with 异步资源管理 with

知识延伸

概念 简述
awaitable 对象 可被 await 的对象(协程、Task、Future)
Task 将协程包装为可调度任务 asyncio.create_task()
Future 低层的异步结果占位符
并发限制 可用 asyncio.Semaphore() 控制并发数量
异步 I/O 库 aiohttp, aiomysql, aioredis, asyncpg