Files
gh-basher83-lunar-claude-pl…/skills/python-uv-scripts/anti-patterns/when-not-to-use.md
2025-11-29 18:00:18 +08:00

7.1 KiB

When NOT to Use Single-File Scripts

This document helps determine when to use a single-file uv script vs. when to use a proper uv project.

Decision Tree

Is this a Python program?
├─ No → Use appropriate language/tool
└─ Yes
    ├─ Is it a one-time task or simple automation?
    │   ├─ Yes → Consider single-file script
    │   └─ No → Use proper uv project
    └─ Does it meet ANY of these criteria?
        ├─ >500 lines of code → Use proper uv project
        ├─ Multiple Python files needed → Use proper uv project
        ├─ Web application or API → Use proper uv project
        ├─ Long-running service → Use proper uv project
        ├─ Complex configuration → Use proper uv project
        ├─ Shared library code → Use proper uv project
        ├─ Heavy ML/data dependencies → Use proper uv project
        └─ None of the above → Single-file script is appropriate

Use Proper uv Project When

1. Code Complexity

Use project if:

  • Script exceeds 500 lines
  • Logic is spread across multiple functions/classes
  • Code would benefit from splitting into modules
  • Complex data models or class hierarchies

Example - Too Complex for Script:

# This needs a proper project structure:
# - 800 lines of code
# - Multiple classes (User, Database, API, Config)
# - Would be clearer as separate modules
# - Needs tests

2. Multiple Files Needed

Use project if:

  • Shared utilities across multiple scripts
  • Common data models used by different tools
  • Reusable library code
  • Multiple entry points

Example:

# This needs a project:
my-tool/
├── src/
│   ├── __init__.py
│   ├── database.py      # Shared by multiple tools
│   ├── models.py        # Common data structures
│   └── utils.py         # Utility functions
├── scripts/
│   ├── import_data.py   # Uses shared code
│   └── export_data.py   # Uses shared code
└── pyproject.toml

3. Web Applications

Use project for:

  • Flask/FastAPI/Django applications
  • REST APIs
  • Web services
  • Applications with routes/controllers

Example - Needs Project:

# Don't use single-file script for web apps:
from flask import Flask, request, jsonify

app = Flask(__name__)

# 50+ routes
# Database models
# Authentication
# Background tasks
# Configuration management

# This should be a proper project structure

4. Long-Running Services

Use project for:

  • Daemons
  • Background workers
  • Queue consumers
  • Services that run continuously

Example:

# Don't use script for services:
# - Runs 24/7
# - Monitors message queue
# - Complex retry logic
# - Logging configuration
# - Health checks
# - Graceful shutdown

# Needs proper project structure with:
# - Proper logging setup
# - Configuration management
# - Process management (systemd/supervisor)

5. Complex Configuration

Use project if:

  • Multiple environment configs (dev/staging/prod)
  • YAML/JSON configuration files
  • Feature flags
  • Database connection pools

Example:

# This needs a project:
config/
├── dev.yaml
├── staging.yaml
└── production.yaml

# Single-file scripts should use simple env vars instead

6. Heavy Dependencies

Use project for:

  • Machine learning frameworks (TensorFlow, PyTorch)
  • Large data processing (PySpark)
  • Complex scientific computing
  • GUI frameworks

Example - Too Heavy:

# /// script
# dependencies = [
#   "tensorflow>=2.15.0",     # ❌ ~500MB download
#   "torch>=2.1.0",           # ❌ ~800MB download
#   "transformers>=4.35.0",   # ❌ Complex dependency tree
# ]
# ///

# Use proper project with managed virtual environment

7. Testing Requirements

Use project if:

  • Comprehensive test suite needed
  • Multiple test files
  • Fixtures and mocking
  • CI/CD integration

Example:

# This needs a project:
tests/
├── unit/
│   ├── test_models.py
│   ├── test_utils.py
│   └── test_api.py
├── integration/
│   └── test_database.py
└── conftest.py

# Can't reasonably organize this with single-file script

8. Team Collaboration

Use project if:

  • Multiple developers working on code
  • Code review processes
  • Versioning and releases
  • Documentation requirements

Single-File Scripts ARE Appropriate For

Good Use Cases

One-time tasks:

# Convert CSV format
# Migrate data between systems
# Clean up old files
# Generate reports

Simple automation:

# Check server health
# Send notifications
# Backup files
# Parse logs

CLI utilities:

# Format files
# Validate data
# Query APIs
# Process input

Prototyping:

# Test API endpoints
# Experiment with libraries
# Quick data analysis
# Proof of concept

Characteristics of Good Single-File Scripts

  • <500 lines of code
  • Self-contained logic
  • Simple, clear purpose
  • Minimal dependencies (1-5 packages)
  • Standalone execution
  • Quick to understand

Examples of Good Single-File Scripts

Example 1: Health Check

#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [
#   "psutil>=5.9.0",
#   "rich>=13.0.0",
# ]
# ///
"""Check system health and display metrics."""

import psutil
from rich import print

def main():
    cpu = psutil.cpu_percent()
    mem = psutil.virtual_memory().percent
    disk = psutil.disk_usage('/').percent

    print(f"CPU: {cpu}% | Memory: {mem}% | Disk: {disk}%")

    if cpu > 80 or mem > 80 or disk > 80:
        print("[red]⚠ High resource usage![/red]")
        exit(1)

if __name__ == "__main__":
    main()

Example 2: API Query

#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [
#   "httpx>=0.27.0",
# ]
# ///
"""Query API and display results."""

import httpx
import sys

def main():
    response = httpx.get("https://api.github.com/users/octocat")
    response.raise_for_status()
    data = response.json()
    print(f"Name: {data['name']}")
    print(f"Public repos: {data['public_repos']}")

if __name__ == "__main__":
    main()

Migration Path

When a script outgrows single-file format:

  1. Create proper uv project:

    uv init my-tool
    cd my-tool
    
  2. Move script logic to src/:

    mv script.py src/my_tool/main.py
    
  3. Add dependencies to pyproject.toml:

    [project]
    dependencies = [
        "httpx>=0.27.0",
        "rich>=13.0.0",
    ]
    
  4. Create entry point in pyproject.toml:

    [project.scripts]
    my-tool = "my_tool.main:main"
    

Summary

Use single-file scripts for:

  • Simple automation (<500 lines)
  • One-off tasks
  • CLI utilities
  • Prototypes
  • Standalone tools

Use proper uv projects for:

  • Complex applications (>500 lines)
  • Multiple files/modules
  • Web applications
  • Long-running services
  • Heavy dependencies
  • Team collaboration
  • Comprehensive testing

When in doubt: Start with a script. If it grows too complex, migrate to a project.