目录

Python异步编程asyncio详解

asyncio 是 Python 的异步编程框架,适合 IO 密集型任务,能大幅提升并发性能。

基本概念

python
import asyncio

async def hello():
    print("Hello")
    await asyncio.sleep(1)  # 模拟IO操作
    print("World")

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

并发执行

python
import asyncio
import time

async def fetch_data(name, delay):
    await asyncio.sleep(delay)
    return f"{name}的数据"

async def main():
    start = time.time()

    # 串行执行:总耗时 = 1 + 2 + 3 = 6秒
    # result1 = await fetch_data("A", 1)
    # result2 = await fetch_data("B", 2)
    # result3 = await fetch_data("C", 3)

    # 并发执行:总耗时 = max(1, 2, 3) = 3秒
    results = await asyncio.gather(
        fetch_data("A", 1),
        fetch_data("B", 2),
        fetch_data("C", 3)
    )

    print(f"结果: {results}")
    print(f"耗时: {time.time() - start:.1f}秒")

asyncio.run(main())

异步 HTTP 请求

python
import asyncio
import aiohttp

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

async def crawl(urls):
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_page(session, url) for url in urls]
        return await asyncio.gather(*tasks)

urls = [f"https://httpbin.org/delay/{i}" for i in range(1, 6)]
results = asyncio.run(crawl(urls))

信号量控制并发

python
import asyncio

async def limited_task(sem, task_id):
    async with sem:
        print(f"任务 {task_id} 开始")
        await asyncio.sleep(1)
        print(f"任务 {task_id} 完成")
        return task_id

async def main():
    sem = asyncio.Semaphore(3)  # 最多同时3个

    tasks = [limited_task(sem, i) for i in range(10)]
    results = await asyncio.gather(*tasks)
    print(f"完成: {results}")

asyncio.run(main())

异步上下文管理器

python
import asyncio

class AsyncDatabase:
    async def __aenter__(self):
        print("连接数据库")
        await asyncio.sleep(0.5)
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        print("关闭数据库连接")
        await asyncio.sleep(0.5)

    async def query(self, sql):
        await asyncio.sleep(0.1)
        return f"结果: {sql}"

async def main():
    async with AsyncDatabase() as db:
        result = await db.query("SELECT * FROM users")
        print(result)

asyncio.run(main())

TaskGroup(Python 3.11+)

python
import asyncio

async def main():
    async with asyncio.TaskGroup() as tg:
        task1 = tg.create_task(fetch_data("A", 1))
        task2 = tg.create_task(fetch_data("B", 2))

    # TaskGroup 结束后所有任务完成
    print(task1.result(), task2.result())

生产者-消费者

python
import asyncio

async def producer(queue, items):
    for item in items:
        await queue.put(item)
        print(f"生产: {item}")
        await asyncio.sleep(0.5)
    await queue.put(None)  # 结束信号

async def consumer(queue):
    while True:
        item = await queue.get()
        if item is None:
            break
        print(f"消费: {item}")
        await asyncio.sleep(1)
    print("消费者结束")

async def main():
    queue = asyncio.Queue(maxsize=5)
    await asyncio.gather(
        producer(queue, range(10)),
        consumer(queue)
    )

asyncio.run(main())

总结

asyncio 适合网络请求、文件 IO 等等待型任务。async/await 语法让异步代码看起来像同步代码,asyncio.gather 实现并发,Semaphore 控制并发数。但要注意 asyncio 不适合 CPU 密集型任务(应使用 multiprocessing)。