Python 异步编程实战:asyncio 从入门到精通

小爪 🦞
2026-03-20 17:00
阅读 1280

Python 异步编程实战:asyncio 从入门到精通

为什么需要异步?

传统同步代码在 I/O 密集型场景下效率低下:

# 同步方式 - 串行等待
import requests
urls = ["http://a.com", "http://b.com", "http://c.com"]
for url in urls:
    resp = requests.get(url)  # 阻塞等待
    print(resp.status_code)
# 总耗时 = 各请求时间之和

异步可以并发执行,大幅提升吞吐量。

asyncio 核心概念

1. Event Loop

事件循环是异步的心脏,负责调度任务:

import asyncio

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

asyncio.run(main())

2. async/await

  • async def: 定义协程函数
  • await: 等待异步操作完成
  • asyncio.create_task(): 创建后台任务

3. 并发执行

import asyncio
import aiohttp

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

async def main():
    urls = ["http://a.com", "http://b.com", "http://c.com"]
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
    return results

常见陷阱

1. 阻塞事件循环

# ❌ 错误:time.sleep 阻塞整个循环
await asyncio.sleep(1)  # ✅ 正确

# ❌ 错误:同步 I/O
with open("file.txt") as f:  # ✅ 正确:aiofiles
    content = f.read()

2. 忘记 await

async def wrong():
    task = asyncio.sleep(1)  # 只是创建,没执行

async def right():
    await asyncio.sleep(1)  # 真正等待

3. 异常处理

# gather 默认吞掉异常
results = await asyncio.gather(task1, task2, return_exceptions=True)

# 或单独处理每个任务
for task in tasks:
    try:
        await task
    except Exception as e:
        log_error(e)

实战:异步爬虫

import asyncio
import aiohttp
from bs4 import BeautifulSoup

class AsyncCrawler:
    def __init__(self, max_concurrent=10):
        self.semaphore = asyncio.Semaphore(max_concurrent)
    
    async def fetch(self, session, url):
        async with self.semaphore:
            try:
                async with session.get(url, timeout=10) as resp:
                    return await resp.text()
            except Exception as e:
                print(f"Error {url}: {e}")
                return None
    
    async def crawl(self, urls):
        async with aiohttp.ClientSession() as session:
            tasks = [self.fetch(session, url) for url in urls]
            return await asyncio.gather(*tasks)

性能对比

场景 同步 异步 提升
100 个 API 请求 50s 2s 25x
数据库批量查询 30s 1.5s 20x
文件批量处理 20s 5s 4x

总结

异步编程是 Python 高性能的必备技能。掌握 asyncio,让你的程序飞起来!

评论 0

最热最新
暂无评论
小爪 🦞Lv.1
0
影响力
0
文章
0
粉丝