
Python Anti Patterns
Run a Python anti-pattern checklist before merge or when debugging flaky behavior caused by duplicated retries, poor error handling, or other known bad habits.
Overview
Python Anti-Patterns is an agent skill most often used in Ship (also Build, Operate) that applies a checklist of common Python mistakes during review and debugging.
Install
npx skills add https://github.com/wshobson/agents --skill python-anti-patternsWhat is this skill?
- Reference checklist of common Python mistakes and anti-patterns to avoid
- Infrastructure section covers scattered timeout/retry logic with concrete bad-vs-good examples
- Explicit When to Use triggers: pre-merge review, mysterious bugs, teaching, standards, legacy refactor
- Pairs conceptually with python-design-patterns for positive architecture guidance
- Centralized decorators and client wrappers recommended over duplicated HTTP timeout blocks
Adoption & trust: 7.8k installs on skills.sh; 36.5k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your agent-generated Python sprinkles the same timeout handling and other bad habits everywhere, and bugs show up only after merge.
Who is it for?
Indie developers using Claude or Cursor to write Python APIs, scripts, and workers who want a lightweight gate before merge.
Skip if: Greenfield tutorials where you only need hello-world examples, or teams that already enforce the same rules via ruff, mypy, and mandatory human review with no agent in the loop.
When should I use this skill?
Use when reviewing Python code for common anti-patterns, before finalizing implementations, or when debugging issues that might stem from known bad practices.
What do I get? / Deliverables
Review passes catch duplicated infrastructure logic and other anti-patterns early so you refactor toward shared helpers before shipping.
- Annotated list of anti-pattern hits
- Suggested refactors toward centralized helpers or decorators
- Pre-merge review summary for the author
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Code review is the canonical shelf because the skill is framed as a pre-merge and pre-finalization checklist. Review subphase matches explicit triggers like reviewing code before merge and establishing team standards.
Where it fits
Ask the agent to scan a PR for scattered requests timeout blocks before you approve merge.
Finalize a third-party webhook client and verify retries are not copy-pasted per endpoint.
Investigate intermittent API failures and check whether exceptions are swallowed against the anti-pattern list.
Quick sanity pass on a throwaway prototype so bad habits do not carry into the production repo.
How it compares
Use as a procedural review checklist skill, not as a linter replacement—pair with formatters and type checkers for machine-enforced rules.
Common Questions / FAQ
Who is python-anti-patterns for?
Solo and small-team Python builders who want their agent to self-check implementations against a curated anti-pattern list before merge or during refactor.
When should I use python-anti-patterns?
Use it in Ship before merging PRs, in Build while finishing integrations or scripts, and in Operate when debugging production issues that might stem from duplicated retries, poor error handling, or similar habits called out in the checklist.
Is python-anti-patterns safe to install?
It is documentation-style procedural knowledge with no inherent network access; still review the Security Audits panel on this Prism page and pin the skill version you trust.
SKILL.md
READMESKILL.md - Python Anti Patterns
# Python Anti-Patterns Checklist A reference checklist of common mistakes and anti-patterns in Python code. Review this before finalizing implementations to catch issues early. ## When to Use This Skill - Reviewing code before merge - Debugging mysterious issues - Teaching or learning Python best practices - Establishing team coding standards - Refactoring legacy code **Note:** This skill focuses on what to avoid. For guidance on positive patterns and architecture, see the `python-design-patterns` skill. ## Infrastructure Anti-Patterns ### Scattered Timeout/Retry Logic ```python # BAD: Timeout logic duplicated everywhere def fetch_user(user_id): try: return requests.get(url, timeout=30) except Timeout: logger.warning("Timeout fetching user") return None def fetch_orders(user_id): try: return requests.get(url, timeout=30) except Timeout: logger.warning("Timeout fetching orders") return None ``` **Fix:** Centralize in decorators or client wrappers. ```python # GOOD: Centralized retry logic @retry(stop=stop_after_attempt(3), wait=wait_exponential()) def http_get(url: str) -> Response: return requests.get(url, timeout=30) ``` ### Double Retry ```python # BAD: Retrying at multiple layers @retry(max_attempts=3) # Application retry def call_service(): return client.request() # Client also has retry configured! ``` **Fix:** Retry at one layer only. Know your infrastructure's retry behavior. ### Hard-Coded Configuration ```python # BAD: Secrets and config in code DB_HOST = "prod-db.example.com" API_KEY = "sk-12345" def connect(): return psycopg.connect(f"host={DB_HOST}...") ``` **Fix:** Use environment variables with typed settings. ```python # GOOD from pydantic_settings import BaseSettings class Settings(BaseSettings): db_host: str = Field(alias="DB_HOST") api_key: str = Field(alias="API_KEY") settings = Settings() ``` ## Architecture Anti-Patterns ### Exposed Internal Types ```python # BAD: Leaking ORM model to API @app.get("/users/{id}") def get_user(id: str) -> UserModel: # SQLAlchemy model return db.query(UserModel).get(id) ``` **Fix:** Use DTOs/response models. ```python # GOOD @app.get("/users/{id}") def get_user(id: str) -> UserResponse: user = db.query(UserModel).get(id) return UserResponse.from_orm(user) ``` ### Mixed I/O and Business Logic ```python # BAD: SQL embedded in business logic def calculate_discount(user_id: str) -> float: user = db.query("SELECT * FROM users WHERE id = ?", user_id) orders = db.query("SELECT * FROM orders WHERE user_id = ?", user_id) # Business logic mixed with data access if len(orders) > 10: return 0.15 return 0.0 ``` **Fix:** Repository pattern. Keep business logic pure. ```python # GOOD def calculate_discount(user: User, orders: list[Order]) -> float: # Pure business logic, easily testable if len(orders) > 10: return 0.15 return 0.0 ``` ## Error Handling Anti-Patterns ### Bare Exception Handling ```python # BAD: Swallowing all exceptions try: process() except Exception: pass # Silent failure - bugs hidden forever ``` **Fix:** Catch specific exceptions. Log or handle appropriately. ```python # GOOD try: process() except ConnectionError as e: logger.warning("Connection failed, will retry", error=str(e)) raise except ValueError as e: logger.error("Invalid input", error=str(e)) raise BadRequestError(str(e)) ``` ### Ignored Partial Failures ```python # BAD: Stops on first error def process_batch(items): results = [] for item in items: result = process(item) # Raises on error - batch aborted results.appe