bateau84/skills

python-async

Asynchronous Python with asyncio and async/await — coroutines, tasks, TaskGroup, gather, cancellation, timeouts, async context managers, concurrency limits with Semaphore, the httpx.AsyncClient, and not blocking the event loop.

Zobacz źródło

Jak używać

  1. Skopiuj polecenie instalacji i sprawdź źródła przed instalacją we własnym środowisku agenta.
  2. W oryginale sprawdź wymagane narzędzia, dane dostępowe i obsługiwane środowiska.
  3. Opisz dane wejściowe i oczekiwany rezultat; porównaj wynik ze źródłami.
npx skills add https://github.com/bateau84/skills --skill python-async

Przed rozpoczęciem

  • Instalacja nie obejmuje subskrypcji modelu, limitu API ani uprawnień do plików.
  • Gwiazdki i instalacje pokazują aktywność, a nie niezależny test jakości lub bezpieczeństwa.
Oryginalny dokument Skill

Treść z repozytorium z zachowaniem nagłówków, przykładów, kodu, tabel, linków i obrazów.

Pair with python-common-practice for shared verification guidance.

Persona: You are a Python async engineer. You treat the event loop as a single thread you must never block, and you make concurrency explicit.

Asynchronous Python

async/await gives concurrency for I/O-bound work (HTTP, DB, files) on one thread. It does nothing for CPU-bound work — a tight loop inside async def freezes the whole loop. Reach for async when you wait on the network, not when you crunch numbers.

The cardinal rule: never block the loop

A single synchronous call inside a coroutine stalls every other task. Diagnose these with ruff's ASYNC rules (→ See python-lint).

python
# ✗ Bad — blocks the event loop; all concurrent tasks freeze
async def fetch(url):
    return requests.get(url).json()          # sync I/O
    time.sleep(5)                            # sync sleep

# ✓ Good — yields control while waiting
async def fetch(client: httpx.AsyncClient, url):
    resp = await client.get(url)
    return resp.json()
    # await asyncio.sleep(5)  for delays

For unavoidable blocking work (a sync library, CPU work), offload it: await asyncio.to_thread(blocking_fn, arg). This keeps the loop responsive.

Run things concurrently — explicitly

awaiting calls one after another is sequential. To overlap, create tasks. Prefer asyncio.TaskGroup (3.11+): it cancels siblings on failure and propagates errors, so you never leak orphaned tasks.

python
async def fetch_all(client, ids):
    async with asyncio.TaskGroup() as tg:        # structured concurrency
        tasks = [tg.create_task(fetch(client, i)) for i in ids]
    return [t.result() for t in tasks]           # all done, errors already raised

asyncio.gather(*coros) still works but, unless return_exceptions=True, a failure leaves the other tasks running unawaited. Prefer TaskGroup for new code.

Bound concurrency — don't DoS the upstream

Unbounded gather over thousands of items opens thousands of sockets and gets you rate-limited. Cap it with a Semaphore.

python
async def fetch_bounded(client, ids, limit=10):
    sem = asyncio.Semaphore(limit)
    async def one(i):
        async with sem:                  # at most `limit` in flight
            return await fetch(client, i)
    async with asyncio.TaskGroup() as tg:
        tasks = [tg.create_task(one(i)) for i in ids]
    return [t.result() for t in tasks]

This mirrors sortarr's pipeline_concurrency setting — a configurable cap, not unbounded fan-out.

Timeouts and cancellation

Every network call needs a deadline, or one hung upstream hangs your service. Use asyncio.timeout (3.11+) as a context manager; it cancels the body on expiry.

python
async with asyncio.timeout(30):
    data = await fetch(client, url)

Cancellation arrives as asyncio.CancelledError. Never swallow it — let it propagate so structured concurrency can unwind. If you must clean up, re-raise:

python
try:
    await long_op()
except asyncio.CancelledError:
    await cleanup()
    raise                         # ✓ propagate; swallowing breaks cancellation

httpx — reuse one client

Create one AsyncClient per app/lifespan and share it; a fresh client per request throws away connection pooling and TLS reuse. Always close it (or use it as a context manager).

python
async with httpx.AsyncClient(timeout=30) as client:
    ...        # reuse across many requests

Background scheduling (APScheduler)

For periodic jobs, use AsyncIOScheduler so jobs share the app's loop rather than spawning threads. Job functions are coroutines; keep them idempotent (a missed/overlapping run shouldn't corrupt state) and let misfire_grace_time/max_instances=1 guard against pile-ups.

Common mistakes

MistakeFix
requests/time.sleep/sync DB inside async defUse async equivalents or asyncio.to_thread; ruff ASYNC flags these.
Sequential await in a loop for independent callsFan out with TaskGroup; await once.
Unbounded gather over a large listBound with asyncio.Semaphore.
except CancelledError: passRe-raise it; swallowing it breaks shutdown and timeouts.
New httpx.AsyncClient per callOne shared client per lifespan; reuse the pool.
asyncio.run() called from inside a running loopYou're already on the loop; just await.
Calling a coroutine without awaitReturns a coroutine object that never runs (and warns). Await it or make it a task.

Diagnose: 1- ruff check with the ASYNC rule set — finds blocking calls in coroutines 2- run with PYTHONASYNCIODEBUG=1 — surfaces un-awaited coroutines and slow callbacks 3- py-spy dump --pid <pid> — see where a hung event loop is stuck.

References

Powiązane zadania

z tego samego repozytorium

Więcej Skills

Wszystkie Skills
bateau84
Społeczność

behavioral-spec

Derive bounded, implementation-independent requirements from agreed product intent through goal refinement, coverage lenses, obstacle analysis, provenance tracking, and counterexample checks. Use to select, author, and reconcile Behavioral Requirements (BR), Quality Scenarios (QS), and Obligation Contracts (OC) without expanding scope. Not for concrete API/schema/protocol realization (use architectural-spec) or human-centered stories and scenarios (use user-stories-and-scenarios).

Instalacje / 1h
1
GitHub Stars
0
Aktualizacja
18 paź
bateau84
Społeczność

desktop-ui-design

Desktop GUI design for native and hybrid applications: platform conventions (macOS HIG, Windows Fluent, GNOME HIG), menus, keyboard shortcuts, window management, session persistence, native vs Electron/Tauri trade-offs, and accessibility APIs. Use for Swift/AppKit, C/WinUI, GTK+, or Electron/Tauri/Flutter desktop design. Add web-ui-design for a web app shipped as a desktop wrapper. Not for browser-only interfaces, terminal applications (use tui-design), or command-line tools (use cli-design).

Instalacje / 1h
1
GitHub Stars
0
Aktualizacja
18 paź
bateau84
Społeczność

git-commit-discipline

Small coherent commits, explanatory messages, shared-working-tree discipline, and safe undo/recovery. Use when asked to commit, when a diff mixes concerns, when agents share a working tree, or when undoing or recovering Git changes. Not for content conflicts (use git-conflicts).

Instalacje / 1h
1
GitHub Stars
0
Aktualizacja
18 paź
bateau84
Społeczność

golang-dependency-injection

google/wire, uber-go/dig, uber-go/fx, samber/do, manual constructor injection, and service containers in Go. Use when designing service architecture, setting up dependency injection, refactoring tightly coupled code, or managing singletons and service factories.

Instalacje / 1h
1
GitHub Stars
0
Aktualizacja
18 paź