Async Patterns
Core Rules
-
Prefer safe_gather for all new async code - fail-fast, timeout support, cleaner cancellation
-
Use return_exceptions=True for partial-results patterns
-
Always consider timeout for long-running operations
-
Don't migrate existing cleanup code (low priority, both work fine)
safe_gather vs asyncio.gather
safe_gather is better in ALL cases because it provides:
-
Fail-fast cancellation (when not using return_exceptions=True )
-
Timeout support with automatic cleanup
-
Cleaner cancellation handling
See references/safe-gather.md for implementation.
Pattern: All Tasks Must Succeed (fail-fast)
Initialization - all workers must start
await safe_gather(*[worker.pre_run() for worker in workers])
Data fetching - need all pieces
channel_info, front_row, participants = await safe_gather( fetch_channel_info(channel_id), fetch_front_row(channel_id), fetch_participants(channel_id), )
With timeout
results = await safe_gather(*tasks, timeout=30.0)
Pattern: Partial Results Acceptable
Use safe_gather with return_exceptions=True
results = await safe_gather(*batch_tasks, return_exceptions=True) for result in results: if isinstance(result, Exception): logger.error(f"Task failed: {result}") else: process(result)
With timeout
results = await safe_gather(*batch_tasks, return_exceptions=True, timeout=30.0)
Pattern: Cleanup/Shutdown
With timeout for cleanup (don't wait forever)
await safe_gather( service1.shutdown(), service2.shutdown(), return_exceptions=True, timeout=10.0 )
OK to keep existing asyncio.gather for cleanup
await asyncio.gather(*cancelled_tasks, return_exceptions=True)
Migration Decision Tree
Is this new code? ├─ Yes -> Use safe_gather └─ No (existing code) └─ Is it cleanup with return_exceptions=True? ├─ Yes -> Keep asyncio.gather (optional to migrate) └─ No -> Would fail-fast or timeout help? ├─ Yes -> Migrate to safe_gather └─ No -> Low priority
Key Principles
-
Fail-fast by default: If one task fails, cancel the rest
-
Always consider timeout: Long-running operations need timeouts
-
Clean cancellation: Handle CancelledError properly
-
Don't wait forever: Especially for cleanup/shutdown
Reference Files
- references/safe-gather.md - safe_gather implementation
Related Skills
-
/pythonista-testing - Testing async code
-
/pythonista-typing - Async type annotations
-
/pythonista-debugging - Debugging async issues