
Python Resource Management
Ship Python services and scripts that reliably release DB connections, files, and sockets using context managers and async cleanup.
Overview
python-resource-management is an agent skill for the Build phase that teaches deterministic Python cleanup with context managers, async managers, and streaming-safe release patterns.
Install
npx skills add https://github.com/wshobson/agents --skill python-resource-managementWhat is this skill?
- Sync `with` and async `async with` patterns via `__enter__`/`__exit__` and `__aenter__`/`__aexit__`
- `@contextmanager` quick-start for acquire/yield/finally cleanup
- Unconditional `__exit__` cleanup even when exceptions fire
- Guidance on suppressing vs propagating exceptions from `__exit__`
- Covers nested cleanup, streaming with accumulated state, and connection-pool usage
Adoption & trust: 6.7k installs on skills.sh; 36.5k GitHub stars; 2/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are writing Python that opens connections or files but leaks handles or duplicates fragile try/finally blocks everywhere.
Who is it for?
Indie builders shipping Python APIs, workers, or scripts that touch databases, files, or sockets and need production-grade cleanup without boilerplate sprawl.
Skip if: Pure frontend work, one-off notebooks with no external resources, or teams that already standardize on a framework that fully owns connection lifecycle.
When should I use this skill?
Managing connections, file handles, implementing cleanup logic, or building streaming responses with accumulated state.
What do I get? / Deliverables
Your agent implements consistent `with`/`async with` and `@contextmanager` patterns so resources close reliably and exceptions behave predictably.
- Context-manager implementations for connections and I/O
- Async manager variants where needed
- Streaming handlers with guaranteed teardown
Recommended Skills
Journey fit
Resource lifecycle belongs in implementation when backends, integrations, and streaming handlers are written. Connection pools, I/O, and streaming responses are core backend concerns during the build phase.
How it compares
Use for procedural cleanup patterns in SKILL.md, not as a substitute for your ORM or HTTP client’s built-in pooling docs.
Common Questions / FAQ
Who is python-resource-management for?
Solo and indie developers using agent-assisted coding on Python backends, CLIs, and integrations who manage I/O and connections themselves.
When should I use python-resource-management?
During Build when wiring connection pools, file I/O, custom context managers, async resources, or streaming handlers that must flush state on exit.
Is python-resource-management safe to install?
Review the Security Audits panel on this Prism page for install risk and file integrity; the skill teaches code patterns and does not require elevated permissions by itself.
SKILL.md
READMESKILL.md - Python Resource Management
# Python Resource Management Manage resources deterministically using context managers. Resources like database connections, file handles, and network sockets should be released reliably, even when exceptions occur. ## When to Use This Skill - Managing database connections and connection pools - Working with file handles and I/O - Implementing custom context managers - Building streaming responses with state - Handling nested resource cleanup - Creating async context managers ## Core Concepts ### 1. Context Managers The `with` statement ensures resources are released automatically, even on exceptions. ### 2. Protocol Methods `__enter__`/`__exit__` for sync, `__aenter__`/`__aexit__` for async resource management. ### 3. Unconditional Cleanup `__exit__` always runs, regardless of whether an exception occurred. ### 4. Exception Handling Return `True` from `__exit__` to suppress exceptions, `False` to propagate them. ## Quick Start ```python from contextlib import contextmanager @contextmanager def managed_resource(): resource = acquire_resource() try: yield resource finally: resource.cleanup() with managed_resource() as r: r.do_work() ``` ## Fundamental Patterns ### Pattern 1: Class-Based Context Manager Implement the context manager protocol for complex resources. ```python class DatabaseConnection: """Database connection with automatic cleanup.""" def __init__(self, dsn: str) -> None: self._dsn = dsn self._conn: Connection | None = None def connect(self) -> None: """Establish database connection.""" self._conn = psycopg.connect(self._dsn) def close(self) -> None: """Close connection if open.""" if self._conn is not None: self._conn.close() self._conn = None def __enter__(self) -> "DatabaseConnection": """Enter context: connect and return self.""" self.connect() return self def __exit__( self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, ) -> None: """Exit context: always close connection.""" self.close() # Usage with context manager (preferred) with DatabaseConnection(dsn) as db: result = db.execute(query) # Manual management when needed db = DatabaseConnection(dsn) db.connect() try: result = db.execute(query) finally: db.close() ``` ### Pattern 2: Async Context Manager For async resources, implement the async protocol. ```python class AsyncDatabasePool: """Async database connection pool.""" def __init__(self, dsn: str, min_size: int = 1, max_size: int = 10) -> None: self._dsn = dsn self._min_size = min_size self._max_size = max_size self._pool: asyncpg.Pool | None = None async def __aenter__(self) -> "AsyncDatabasePool": """Create connection pool.""" self._pool = await asyncpg.create_pool( self._dsn, min_size=self._min_size, max_size=self._max_size, ) return self async def __aexit__( self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None, ) -> None: """Close all connections in pool.""" if self._pool is not None: await self._pool.close() async def execute(self, query: str, *args) -> list[dict]: """Execute query using pooled connection.""" async with self._pool.acquire() as conn: return await conn.fetch(query, *args) # Usage async with AsyncDatabasePool(dsn) as pool: users = await pool.execute("SELECT * FROM