mcpField
A
async-python-patterns

async-python-patterns

github.com/wshobson开发41.9k18.3k 次安装2 周前更新
代码仓库

关于 async-python-patterns

为使用 asyncio、并发和 async/await 的 Python 异步开发提供实践指导,适合构建 I/O 密集型应用的开发者,涵盖常见模式、测试和易错点。

主要功能

  1. 01讲解事件循环、协程、任务和 Future
  2. 02展示并发执行与任务管理模式
  3. 03涵盖错误、超时和取消处理
  4. 04指导同步与异步方案选择
  5. 05提供异步测试示例

适用场景

  1. 01构建并发 Web API
  2. 02并发执行数据库和网络 I/O
  3. 03创建并发网络爬虫
  4. 04开发 WebSocket 或后台任务系统

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/wshobson/agents --skill async-python-patterns

安装后在 Claude Code 中输入/async-python-patterns确认已加载。

附带文件references/details.md

详细介绍

异步 Python 模式

使用 asyncio、并发编程模式和 async/await 实现异步 Python 应用的综合指南,助你构建高性能、非阻塞系统。

何时使用本技能

  • 构建异步 Web API(FastAPI、aiohttp、Sanic)
  • 实现并发 I/O 操作(数据库、文件、网络)
  • 创建带并发请求的网页爬虫
  • 开发实时应用(WebSocket 服务、聊天系统)
  • 同时处理多个独立任务
  • 构建采用异步通信的微服务
  • 优化 I/O 密集型工作负载
  • 实现异步后台任务与队列

同步 vs 异步决策指南

在采用异步之前,请先考虑它是否适合你的用例。

用例推荐方案
大量并发的网络/数据库调用asyncio
CPU 密集型计算multiprocessing 或线程池
I/O 与 CPU 混合用 asyncio.to_thread() 卸载 CPU 工作
简单脚本、连接数少同步(更简单,更易调试)
高并发的 Web API异步框架(FastAPI、aiohttp)

关键规则: 在同一条调用路径上,要么完全同步,要么完全异步。混用会带来隐蔽的阻塞和复杂性。

核心概念

1. 事件循环

事件循环是 asyncio 的核心,负责管理和调度异步任务。

关键特性:

  • 单线程协作式多任务
  • 调度协程执行
  • 以非阻塞方式处理 I/O 操作
  • 管理回调和 future
2. 协程

用 async def 定义的函数,可以暂停和恢复。

语法:

async def my_coroutine():
    result = await some_async_operation()
    return result
3. 任务

在事件循环上并发运行的已调度协程。

4. Future

表示异步操作最终结果的底层对象。

5. 异步上下文管理器

支持 async with 的资源,可进行正确的清理。

6. 异步迭代器

支持 async for 的对象,用于遍历异步数据源。

快速开始

import asyncio

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

# Python 3.7+
asyncio.run(main())

基础模式

模式 1:基本 async/await
import asyncio

async def fetch_data(url: str) -> dict:
    """Fetch data from URL asynchronously."""
    await asyncio.sleep(1)  # Simulate I/O
    return {"url": url, "data": "result"}

async def main():
    result = await fetch_data("https://api.example.com")
    print(result)

asyncio.run(main())
模式 2:使用 gather() 并发执行
import asyncio
from typing import List

async def fetch_user(user_id: int) -> dict:
    """Fetch user data."""
    await asyncio.sleep(0.5)
    return {"id": user_id, "name": f"User {user_id}"}

async def fetch_all_users(user_ids: List[int]) -> List[dict]:
    """Fetch multiple users concurrently."""
    tasks = [fetch_user(uid) for uid in user_ids]
    results = await asyncio.gather(*tasks)
    return results

async def main():
    user_ids = [1, 2, 3, 4, 5]
    users = await fetch_all_users(user_ids)
    print(f"Fetched {len(users)} users")

asyncio.run(main())
模式 3:任务创建与管理
import asyncio

async def background_task(name: str, delay: int):
    """Long-running background task."""
    print(f"{name} started")
    await asyncio.sleep(delay)
    print(f"{name} completed")
    return f"Result from {name}"

async def main():
    # Create tasks
    task1 = asyncio.create_task(background_task("Task 1", 2))
    task2 = asyncio.create_task(background_task("Task 2", 1))

    # Do other work
    print("Main: doing other work")
    await asyncio.sleep(0.5)

    # Wait for tasks
    result1 = await task1
    result2 = await task2

    print(f"Results: {result1}, {result2}")

asyncio.run(main())
模式 4:异步代码中的错误处理
import asyncio
from typing import List, Optional

async def risky_operation(item_id: int) -> dict:
    """Operation that might fail."""
    await asyncio.sleep(0.1)
    if item_id % 3 == 0:
        raise ValueError(f"Item {item_id} failed")
    return {"id": item_id, "status": "success"}

async def safe_operation(item_id: int) -> Optional[dict]:
    """Wrapper with error handling."""
    try:
        return await risky_operation(item_id)
    except ValueError as e:
        print(f"Error: {e}")
        return None

async def process_items(item_ids: List[int]):
    """Process multiple items with error handling."""
    tasks = [safe_operation(iid) for iid in item_ids]
    results = await asyncio.gather(*tasks, return_exceptions=True)

    # Filter out failures
    successful = [r for r in results if r is not None and not isinstance(r, Exception)]
    failed = [r for r in results if r is None or isinstance(r, Exception)]

    print(f"Success: {len(successful)}, Failed: {len(failed)}")
    return successful

asyncio.run(process_items([1, 2, 3, 4, 5, 6]))
模式 5:超时处理
import asyncio

async def slow_operation(delay: int) -> str:
    """Operation that takes time."""
    await asyncio.sleep(delay)
    return f"Completed after {delay}s"

async def with_timeout():
    """Execute operation with timeout."""
    try:
        result = await asyncio.wait_for(slow_operation(5), timeout=2.0)
        print(result)
    except asyncio.TimeoutError:
        print("Operation timed out")

asyncio.run(with_timeout())

详细示例与模式

详细章节(以 ## Advanced Patterns 开头)位于 references/details.md。当上面的导航摘要不够用时,请阅读该文件。

常见陷阱

1. 忘记 await
# Wrong - returns coroutine object, doesn't execute
result = async_function()

# Correct
result = await async_function()
2. 阻塞事件循环
# Wrong - blocks event loop
import time
async def bad():
    time.sleep(1)  # Blocks!

# Correct
async def good():
    await asyncio.sleep(1)  # Non-blocking
3. 未处理取消
async def cancelable_task():
    """Task that handles cancellation."""
    try:
        while True:
            await asyncio.sleep(1)
            print("Working...")
    except asyncio.CancelledError:
        print("Task cancelled, cleaning up...")
        # Perform cleanup
        raise  # Re-raise to propagate cancellation
4. 混用同步与异步代码
# Wrong - can't call async from sync directly
def sync_function():
    result = await async_function()  # SyntaxError!

# Correct
def sync_function():
    result = asyncio.run(async_function())

测试异步代码

import asyncio
import pytest

# Using pytest-asyncio
@pytest.mark.asyncio
async def test_async_function():
    """Test async function."""
    result = await fetch_data("https://api.example.com")
    assert result is not None

@pytest.mark.asyncio
async def test_with_timeout():
    """Test with timeout."""
    with pytest.raises(asyncio.TimeoutError):
        await asyncio.wait_for(slow_operation(5), timeout=1.0)

评论

支持 Markdown