Generated banner for Python Resource Management
Generated logo for Python Resource Management

Python Resource Management

Seth HobsonCommunityCreated by Seth Hobson

  • Skill
  • Guidelines
  • Software development
  • MIT
  • No issues found

From the author

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 description by Seth Hobson

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides best practices and design patterns for managing resources in Python, such as file handles, database connections, and network sockets. It focuses on using context managers to ensure reliable cleanup, even when exceptions occur, and covers both synchronous and asynchronous protocols. The content includes implementation strategies for class-based context managers, the use of decorators, and advanced techniques for handling streaming data, exception suppression, and dynamic resource management.

What it does

  • Explains the implementation of sync and async context managers using protocol methods.
  • Demonstrates how to use the contextlib decorator for simplified resource management.
  • Provides patterns for unconditional resource cleanup to prevent leaks.
  • Offers techniques for selective exception suppression within context managers.
  • Details methods for efficient stream accumulation and metric tracking.
  • Shows how to manage dynamic numbers of resources using ExitStack.

When to use it

  • When you need to ensure resources like database connections or file handles are closed reliably.
  • When implementing custom logic that requires setup and teardown phases.
  • When building streaming responses that require state accumulation.
  • When you need to handle complex, nested, or dynamic resource cleanup scenarios.

Advantages

  • Promotes deterministic resource release, reducing the risk of memory or connection leaks.
  • Provides clear, reusable patterns for both synchronous and asynchronous codebases.
  • Encourages robust error handling by standardizing how exceptions are managed during cleanup.
  • Offers efficient approaches for data processing and stream management.

Usage examples

“How do I ensure a file is closed even if an error occurs during processing?”
The skill provides a pattern using the 'with' statement or a custom context manager that implements the __exit__ method to guarantee the file is closed.
“How can I manage multiple database connections dynamically?”
The skill demonstrates using 'ExitStack' to handle a dynamic number of resources, ensuring all are cleaned up properly.
“How do I suppress specific errors in a context manager?”
The skill shows how to implement the __exit__ method to check the exception type and return True only for specific, expected errors.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/wshobson/python-resource-management/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip python-resource-management.zip -d .agents/skills

Documentation by Seth Hobson

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

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.

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.

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 users WHERE active = $1", True)
Pattern 3: Using @contextmanager Decorator

Simplify context managers with the decorator for straightforward cases.

from contextlib import contextmanager, asynccontextmanager
import time
import structlog

logger = structlog.get_logger()

@contextmanager
def timed_block(name: str):
    """Time a block of code."""
    start = time.perf_counter()
    try:
        yield
    finally:
        elapsed = time.perf_counter() - start
        logger.info(f"{name} completed", duration_seconds=round(elapsed, 3))

# Usage
with timed_block("data_processing"):
    process_large_dataset()

@asynccontextmanager
async def database_transaction(conn: AsyncConnection):
    """Manage database transaction."""
    await conn.execute("BEGIN")
    try:
        yield conn
        await conn.execute("COMMIT")
    except BaseException:  # also roll back on asyncio.CancelledError
        await conn.execute("ROLLBACK")
        raise

# Usage
async with database_transaction(conn) as tx:
    await tx.execute("INSERT INTO users ...")
    await tx.execute("INSERT INTO audit_log ...")
Pattern 4: Unconditional Resource Release

Always clean up resources in __exit__, regardless of exceptions.

class FileProcessor:
    """Process file with guaranteed cleanup."""

    def __init__(self, path: str) -> None:
        self._path = path
        self._file: IO | None = None
        self._temp_files: list[Path] = []

    def __enter__(self) -> "FileProcessor":
        self._file = open(self._path, "r")
        return self

    def __exit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None:
        """Clean up all resources unconditionally."""
        # Close main file
        if self._file is not None:
            self._file.close()

        # Clean up any temporary files
        for temp_file in self._temp_files:
            try:
                temp_file.unlink()
            except OSError:
                pass  # Best effort cleanup

        # Return None/False to propagate any exception

Detailed worked examples and patterns

Detailed sections (starting with ## Advanced Patterns) live in references/details.md. Read that file when the navigation summary above is insufficient.

Best Practices Summary

  1. Always use context managers - For any resource that needs cleanup

  2. Clean up unconditionally - __exit__ runs even on exception

  3. Don't suppress unexpectedly - Return False unless suppression is intentional

  4. Use @contextmanager - For simple resource patterns

  5. Implement both protocols - Support with and manual management

  6. Use ExitStack - For dynamic numbers of resources

  7. Accumulate efficiently - List + join, not string concatenation

  8. Track metrics - Time-to-first-byte matters for streaming

  9. Document behavior - Especially exception suppression

  10. Test cleanup paths - Verify resources are released on errors

Files

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Python

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Seth Hobson
Publisher
Seth Hobson (Community)
Source
wshobson/agents · plugins/python-development/skills/python-resource-management · commit 4bde316
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Seth Hobson or Seth Hobson.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download python-resource-management.zip