Python asyncio 异步编程入门

asyncio 是 Python 3.4+ 引入的标准库,用于编写并发代码。本文将带你快速入门 asyncio 的核心概念。

为什么要用异步?

在传统的同步编程中,当程序遇到 I/O 操作(如网络请求、文件读写)时,线程会阻塞等待。而异步编程允许我们在等待 I/O 时去执行其他任务,极大地提高了资源利用率。

核心概念

1. coroutine(协程)

使用 async def 定义的函数就是协程:

1
2
3
4
5
6
7
8
9
import asyncio

async def say_hello():
print("Hello")
await asyncio.sleep(1)
print("World")

# 运行协程
asyncio.run(say_hello())

2. await 关键字

await 用于等待一个可等待对象(协程、任务、Future)完成。注意:await 只能在 async def 函数中使用。

3. Task(任务)

任务用于并发调度协程:

1
2
3
4
5
6
7
8
async def main():
task1 = asyncio.create_task(fetch_data("url1"))
task2 = asyncio.create_task(fetch_data("url2"))

result1 = await task1
result2 = await task2

print(result1, result2)

4. gather 并发执行

1
2
3
4
5
6
7
async def main():
results = await asyncio.gather(
fetch_data("url1"),
fetch_data("url2"),
fetch_data("url3"),
)
print(results)

实战示例:并发爬虫

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

async def fetch(session, url):
async with session.get(url) as response:
return await response.text()

async def main():
urls = [
"https://api.github.com",
"https://api.github.com/users/python",
"https://api.github.com/users/google",
]

async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
results = await asyncio.gather(*tasks)

for url, result in zip(urls, results):
print(f"{url}: {len(result)} bytes")

asyncio.run(main())

注意事项

  1. 不要在协程中使用阻塞操作:如 time.sleep(),应使用 asyncio.sleep()
  2. 事件循环asyncio.run() 会自动管理事件循环,高级用法可手动控制
  3. 异常处理:使用 try/except 包裹 await 语句

总结

asyncio 让 Python 也能高效处理 I/O 密集型任务。虽然学习曲线略陡,但掌握后能够编写出高性能的并发程序。

推荐阅读 官方文档 深入学习。