Skip to content
Back to skills

Async Python Patterns

ASecurity

当用 asyncio 写 I/O 密集的异步并发(API/爬虫/WebSocket/批量请求/后台队列)时使用;做出带超时、限流、取消与结构化错误处理的 async/await 代码与排错方案;不适用于 CPU 密集任务、同步脚本足够或运行环境无事件循环的场景;触发词:asyncio、async/await、gather、并发请求、协程。

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 19, 2026
ai-agentspythongokotlinsqlfastapitestingcode-reviewapibackendperformance

Works with

  • cursor
  • cli
  • api

Security analysis

A100/100

Scanned September 19, 2026

npx -y skills add findscripter/everything-skills --skill async-python-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Async Python Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Async Python Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/findscripter-async-python-patterns/badge)](https://www.skillsdirectory.com/skills/findscripter-async-python-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: async-python-patterns
title: Python 异步并发编程模式
description: 当用 asyncio 写 I/O 密集的异步并发(API/爬虫/WebSocket/批量请求/后台队列)时使用;做出带超时、限流、取消与结构化错误处理的 async/await 代码与排错方案;不适用于 CPU 密集任务、同步脚本足够或运行环境无事件循环的场景;触发词:asyncio、async/await、gather、并发请求、协程。
domain: 研发/backend
triggers: [asyncio, async/await, gather, 并发请求, 协程, aiohttp, 事件循环, 异步爬虫, WebSocket, 信号量限流, run_in_executor, 生产者消费者, asyncio.Queue, 超时, TimeoutError]
tags: [python, asyncio, concurrency, async-await, backend, engineering]
level: 进阶
status: stable
agents: [claude-code, codex, cursor, gemini-cli]
tools: [python]
requires: []
related: [fastapi-async-api, python-performance-optimization, go-concurrency-patterns, kotlin-coroutines-flow]
combines_with: [bullmq-job-queue, python-testing-pytest, error-handling-patterns]
license: MIT
source: sickn33/agentic-awesome-skills
source_license: MIT
---
## 何时使用

- 用 asyncio 构建/优化 **I/O 密集**型系统:异步 Web API(FastAPI、aiohttp、Sanic)、并发数据库/文件/网络访问。
- 并发爬虫、批量 HTTP 请求;WebSocket 服务、聊天等实时应用;异步后台任务与队列。
- 同时跑多个相互独立、需要等待的任务;微服务间异步通信。
- 触发词:asyncio、async/await、gather、并发请求、协程、aiohttp、信号量限流、超时。

不该用的边界:
- **CPU 密集**、几乎没有 I/O 的计算 → 异步无收益,用多进程(`multiprocessing`/`ProcessPoolExecutor`);必须在协程里跑阻塞计算时用 `loop.run_in_executor` 丢到线程/进程池。
- 一段简单同步脚本就够用 → 别引入事件循环增加复杂度。
- 运行环境不支持 asyncio/事件循环(如某些受限沙箱、已有同步框架且无法改造)→ 不适用。
- 想要并发但只是顺序 `await` 多个协程 → 那是串行,不是并发;并发要靠 `create_task`/`gather`。

## 步骤 / 指令

```
1. 判定工作负载:I/O 密集才用 asyncio;先确认目标(吞吐/延迟)与运行时约束。
2. 选并发原语并定义取消规则:
   - 入口统一用 asyncio.run(main())(Python 3.7+)。
   - 多任务并发:asyncio.gather(*tasks) 或 asyncio.create_task() + 后续 await。
   - 队列解耦:asyncio.Queue(生产者/消费者)。
   - 资源池/限流:asyncio.Semaphore;连接复用用 aiohttp.TCPConnector。
3. 加固:每个外部调用配 timeout(asyncio.wait_for / ClientTimeout);
   队列设 maxsize 做背压;gather(..., return_exceptions=True) 收集失败而非整体崩。
4. 正确处理取消:捕获 asyncio.CancelledError 做清理后 re-raise,勿吞掉。
5. 隔离阻塞:绝不在协程里调 time.sleep / 阻塞 IO / 重计算;用 await asyncio.sleep
   或 loop.run_in_executor 包装。
6. 测试与调试:用 pytest-asyncio(@pytest.mark.asyncio)覆盖正常/超时/取消路径。
```

规则:
- 协程必须 `await` 才执行;`f()` 只返回协程对象不会跑。
- 单事件循环单线程:任何阻塞调用都会卡住所有协程。
- 失败要么 `try/except` 包裹,要么 `gather(return_exceptions=True)` 收集,二选一,别裸奔。
- 超时是默认配置而非可选项;外部 I/O 一律设上限。

## 示例

并发抓取(gather + 超时 + 错误隔离 + 连接池):
```python
import asyncio, aiohttp
from typing import List, Dict

async def fetch(session: aiohttp.ClientSession, url: str) -> Dict:
    try:
        async with session.get(url, timeout=aiohttp.ClientTimeout(total=10)) as r:
            return {"url": url, "status": r.status, "length": len(await r.text())}
    except Exception as e:
        return {"url": url, "error": str(e)}

async def scrape(urls: List[str]) -> List[Dict]:
    conn = aiohttp.TCPConnector(limit=100, limit_per_host=10)  # 连接池
    async with aiohttp.ClientSession(connector=conn) as session:
        return await asyncio.gather(*(fetch(session, u) for u in urls))

asyncio.run(scrape(["https://httpbin.org/delay/1"]))
```

信号量限流(控制最大并发):
```python
async def api_call(url, sem: asyncio.Semaphore):
    async with sem:                       # 同时最多 N 个进入
        await asyncio.sleep(0.5)
        return {"url": url, "status": 200}

async def main(urls, max_concurrent=3):
    sem = asyncio.Semaphore(max_concurrent)
    return await asyncio.gather(*(api_call(u, sem) for u in urls))
```

超时控制:
```python
try:
    result = await asyncio.wait_for(slow_op(5), timeout=2.0)
except asyncio.TimeoutError:
    print("Operation timed out")
```

把阻塞操作丢进线程池(避免卡事件循环):
```python
import concurrent.futures
async def run_blocking(data):
    loop = asyncio.get_event_loop()
    with concurrent.futures.ThreadPoolExecutor() as pool:
        return await loop.run_in_executor(pool, blocking_operation, data)
```

正确处理取消:
```python
async def cancelable_task():
    try:
        while True:
            await asyncio.sleep(1)
    except asyncio.CancelledError:
        # 在这里做清理
        raise   # 必须 re-raise 以传播取消
```

测试(pytest-asyncio):
```python
@pytest.mark.asyncio
async def test_with_timeout():
    with pytest.raises(asyncio.TimeoutError):
        await asyncio.wait_for(slow_op(5), timeout=1.0)
```

## 注意事项

- 忘记 `await`:`result = async_function()` 拿到的是协程对象、不会执行;要 `await async_function()`。
- 阻塞事件循环:协程内用 `time.sleep(1)` 会冻结整个循环;改 `await asyncio.sleep(1)`;CPU/阻塞活全部丢 `run_in_executor`。
- 不处理取消:捕获 `CancelledError` 清理后必须 `raise` 重新抛出,否则取消语义被破坏。
- 同步/异步混用:`def` 函数里不能直接 `await`(语法错误);从同步侧进入异步用 `asyncio.run(coro())`,但别在已有事件循环内再次 `asyncio.run`。
- 队列要设 `maxsize` 做背压;生产者用哨兵值(如 `None`)通知消费者结束,并配合 `queue.join()` / `task_done()`。
- 性能:复用连接(连接池)、按批处理(batch + gather)、用 `Semaphore` 限流防止打爆下游。
- 共享可变状态用 `asyncio.Lock` 保护,避免在 `await` 之间被穿插改写。
- 别把它当 CPU 加速器:异步只省 I/O 等待时间,纯计算请用多进程。
- 常用生态:aiohttp(HTTP 客户端/服务)、FastAPI(异步框架)、asyncpg(PostgreSQL)、motor(MongoDB);官方文档 https://docs.python.org/3/library/asyncio.html。

## 互见

- requires:无。
- related:`code-reviewer`(审查异步代码的取消/超时/竞态等正确性问题)。
- combines_with:无。

---
采编自 sickn33/antigravity-awesome-skills(MIT 许可)。

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…