Skills · Coding

Python Resource Management

Unverified28/40

Python resource management with context managers, cleanup patterns, and streaming. Use when managing connections, file handles, implementing cleanup logic, or building streaming responses with accumulated state.

Originally by wshobson · MIT

Claude CodePartialHas SKILL.md but declares no allowed-tools — Claude Code will ask for permission each time
CursorPartialPlain prose you can paste in — but no Cursor rules file
CodexPartialPlain prose you can paste in — but no AGENTS.md
Gemini CLIPartialPlain prose you can paste in
CopilotPartialPlain prose you can paste in — but no Copilot instructions file
npx agentalley add python-resource-management

This command does not work yet — the CLI is still being built. Until then, use Raw in the reader below to take the file.

Who is stuck, and on what

Python resource management with context managers, cleanup patterns, and streaming. Use when managing connections, file handles, implementing cleanup logic, or building streaming responses with accumulated state.

The whole source

No sign-in, no blur, nothing truncated
python-resource-management/SKILL.md244 lines6.8 KBRawView on GitHub
Frontmatter — 2 properties
namepython-resource-management
descriptionPython resource management with context managers, cleanup patterns, and streaming. Use when managing connections, file handles, implementing cleanup logic, or building streaming responses with accumulated state.
1---
2name: python-resource-management
3description: Python resource management with context managers, cleanup patterns, and streaming. Use when managing connections, file handles, implementing cleanup logic, or building streaming responses with accumulated state.
4---A5No allowed-tools declared — no way to tell what this skill may touch
5 
6# Python Resource Management
7 
8Manage resources deterministically using context managers. Resources like database connections, file handles, and network sockets should be released reliably, even when exceptions occur.
9 
10## When to Use This Skill
11 
12- Managing database connections and connection pools
13- Working with file handles and I/O
14- Implementing custom context managers
15- Building streaming responses with state
16- Handling nested resource cleanup
17- Creating async context managers
18 
19## Core Concepts
20 
21### 1. Context Managers
22 
23The `with` statement ensures resources are released automatically, even on exceptions.
24 
25### 2. Protocol Methods
26 
27`__enter__`/`__exit__` for sync, `__aenter__`/`__aexit__` for async resource management.
28 
29### 3. Unconditional Cleanup
30 
31`__exit__` always runs, regardless of whether an exception occurred.
32 
33### 4. Exception Handling
34 
35Return `True` from `__exit__` to suppress exceptions, `False` to propagate them.
36 
37## Quick Start
38 
39```python
40from contextlib import contextmanager
41 
42@contextmanager
43def managed_resource():
44 resource = acquire_resource()
45 try:
46 yield resource
47 finally:
48 resource.cleanup()
49 
50with managed_resource() as r:
51 r.do_work()
52```
53 
54## Fundamental Patterns
55 
56### Pattern 1: Class-Based Context Manager
57 
58Implement the context manager protocol for complex resources.
59 
60```python
61class DatabaseConnection:
62 """Database connection with automatic cleanup."""
63 
64 def __init__(self, dsn: str) -> None:
65 self._dsn = dsn
66 self._conn: Connection | None = None
67 
68 def connect(self) -> None:
69 """Establish database connection."""
70 self._conn = psycopg.connect(self._dsn)
71 
72 def close(self) -> None:
73 """Close connection if open."""
74 if self._conn is not None:
75 self._conn.close()
76 self._conn = None
77 
78 def __enter__(self) -> "DatabaseConnection":
79 """Enter context: connect and return self."""
80 self.connect()
81 return self
82 
83 def __exit__(
84 self,
85 exc_type: type[BaseException] | None,
86 exc_val: BaseException | None,
87 exc_tb: TracebackType | None,
88 ) -> None:
89 """Exit context: always close connection."""
90 self.close()
91 
92# Usage with context manager (preferred)
93with DatabaseConnection(dsn) as db:
94 result = db.execute(query)
95 
96# Manual management when needed
97db = DatabaseConnection(dsn)
98db.connect()
99try:
100 result = db.execute(query)
101finally:
102 db.close()
103```
104 
105### Pattern 2: Async Context Manager
106 
107For async resources, implement the async protocol.
108 
109```python
110class AsyncDatabasePool:
111 """Async database connection pool."""
112 
113 def __init__(self, dsn: str, min_size: int = 1, max_size: int = 10) -> None:
114 self._dsn = dsn
115 self._min_size = min_size
116 self._max_size = max_size
117 self._pool: asyncpg.Pool | None = None
118 
119 async def __aenter__(self) -> "AsyncDatabasePool":
120 """Create connection pool."""
121 self._pool = await asyncpg.create_pool(
122 self._dsn,
123 min_size=self._min_size,
124 max_size=self._max_size,
125 )
126 return self
127 
128 async def __aexit__(
129 self,
130 exc_type: type[BaseException] | None,
131 exc_val: BaseException | None,
132 exc_tb: TracebackType | None,
133 ) -> None:
134 """Close all connections in pool."""
135 if self._pool is not None:
136 await self._pool.close()
137 
138 async def execute(self, query: str, *args) -> list[dict]:
139 """Execute query using pooled connection."""
140 async with self._pool.acquire() as conn:
141 return await conn.fetch(query, *args)A4This skill pulls in web or user content but never says to treat that content as data. A signal, not proof.
142 
143# Usage
144async with AsyncDatabasePool(dsn) as pool:
145 users = await pool.execute("SELECT * FROM users WHERE active = $1", True)
146```
147 
148### Pattern 3: Using @contextmanager Decorator
149 
150Simplify context managers with the decorator for straightforward cases.
151 
152```python
153from contextlib import contextmanager, asynccontextmanager
154import time
155import structlog
156 
157logger = structlog.get_logger()
158 
159@contextmanager
160def timed_block(name: str):
161 """Time a block of code."""
162 start = time.perf_counter()
163 try:
164 yield
165 finally:
166 elapsed = time.perf_counter() - start
167 logger.info(f"{name} completed", duration_seconds=round(elapsed, 3))
168 
169# Usage
170with timed_block("data_processing"):
171 process_large_dataset()
172 
173@asynccontextmanager
174async def database_transaction(conn: AsyncConnection):
175 """Manage database transaction."""
176 await conn.execute("BEGIN")
177 try:
178 yield conn
179 await conn.execute("COMMIT")
180 except Exception:
181 await conn.execute("ROLLBACK")
182 raise
183 
184# Usage
185async with database_transaction(conn) as tx:
186 await tx.execute("INSERT INTO users ...")
187 await tx.execute("INSERT INTO audit_log ...")
188```
189 
190### Pattern 4: Unconditional Resource Release
191 
192Always clean up resources in `__exit__`, regardless of exceptions.
193 
194```python
195class FileProcessor:
196 """Process file with guaranteed cleanup."""
197 
198 def __init__(self, path: str) -> None:
199 self._path = path
200 self._file: IO | None = None
201 self._temp_files: list[Path] = []
202 
203 def __enter__(self) -> "FileProcessor":
204 self._file = open(self._path, "r")
205 return self
206 
207 def __exit__(
208 self,
209 exc_type: type[BaseException] | None,
210 exc_val: BaseException | None,
211 exc_tb: TracebackType | None,
212 ) -> None:
213 """Clean up all resources unconditionally."""
214 # Close main file
215 if self._file is not None:
216 self._file.close()
217 
218 # Clean up any temporary files
219 for temp_file in self._temp_files:
220 try:
221 temp_file.unlink()
222 except OSError:
223 pass # Best effort cleanup
224 
225 # Return None/False to propagate any exception
226```
227 
228## Detailed worked examples and patterns
229 
230Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.
231 
232## Best Practices Summary
233 
2341. **Always use context managers** - For any resource that needs cleanup
2352. **Clean up unconditionally** - `__exit__` runs even on exception
2363. **Don't suppress unexpectedly** - Return `False` unless suppression is intentional
2374. **Use @contextmanager** - For simple resource patterns
2385. **Implement both protocols** - Support `with` and manual management
2396. **Use ExitStack** - For dynamic numbers of resources
2407. **Accumulate efficiently** - List + join, not string concatenation
2418. **Track metrics** - Time-to-first-byte matters for streaming
2429. **Document behavior** - Especially exception suppression
24310. **Test cleanup paths** - Verify resources are released on errors
244 

Reviews

Installed this one?Write the first review and take the Trailblazer badge.

Reviews only open after a real install, so this is empty — and we leave it empty rather than invent one.

Alternatives

Also in Coding