DEV Community

WDSEGA
WDSEGA

Posted on

Python异步编程实战:asyncio完全指南

同步 vs 异步

同步编程:代码按顺序执行,遇到I/O操作时等待。

import time

def fetch_data(url):
    time.sleep(2)  # 阻塞2秒
    return f"数据来自 {url}"

# 3个请求需要6秒
Enter fullscreen mode Exit fullscreen mode

异步编程:遇到I/O操作时不阻塞,去执行其他任务。

import asyncio

async def fetch_data(url):
    await asyncio.sleep(2)  # 非阻塞
    return f"数据来自 {url}"

async def main():
    tasks = [fetch_data(f"https://api{i}.com") for i in range(3)]
    results = await asyncio.gather(*tasks)
    # 3个请求只需2秒!

asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

核心概念

概念 说明
event loop 事件循环,异步程序的大脑
coroutine 协程,异步函数
await 等待异步操作完成
Task 对协程的封装

实战:异步HTTP请求

import asyncio
import aiohttp

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

async def fetch_all(urls):
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        return await asyncio.gather(*tasks)
Enter fullscreen mode Exit fullscreen mode

实战:异步爬虫

class AsyncCrawler:
    def __init__(self, max_concurrent=10):
        self.semaphore = asyncio.Semaphore(max_concurrent)

    async def crawl(self, start_url, max_pages=50):
        async with aiohttp.ClientSession() as session:
            queue = asyncio.Queue()
            await queue.put(start_url)
            while not queue.empty():
                url = await queue.get()
                html = await self.fetch(session, url)
                links = self.parse_links(html)
                for link in links:
                    await queue.put(link)
Enter fullscreen mode Exit fullscreen mode

常见陷阱

  1. 不要在异步函数中调用同步阻塞代码(如time.sleep、requests.get)
  2. 不要忘记await协程调用
  3. 使用Semaphore控制并发数,避免资源耗尽

性能对比

场景 同步耗时 异步耗时 提升
100个HTTP请求 200秒 2.5秒 80x
1000个数据库查询 500秒 8秒 62x

📢 本文为精简版,完整版包含独家工具推荐和深度分析,请访问 WD Tech Blog 查看!

关注我的博客获取最新科技资讯、AI教程和效率工具推荐!

Top comments (0)