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

364 lines
7.1 KiB
Markdown

# 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
```text
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**:
```python
# 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**:
```text
# 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**:
```python
# 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**:
```python
# 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**:
```text
# 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**:
```python
# /// 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**:
```text
# 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**:
```python
# Convert CSV format
# Migrate data between systems
# Clean up old files
# Generate reports
```
**Simple automation**:
```python
# Check server health
# Send notifications
# Backup files
# Parse logs
```
**CLI utilities**:
```python
# Format files
# Validate data
# Query APIs
# Process input
```
**Prototyping**:
```python
# 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
```python
#!/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
```python
#!/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:
```bash
uv init my-tool
cd my-tool
```
2. Move script logic to `src/`:
```bash
mv script.py src/my_tool/main.py
```
3. Add dependencies to `pyproject.toml`:
```toml
[project]
dependencies = [
"httpx>=0.27.0",
"rich>=13.0.0",
]
```
4. Create entry point in `pyproject.toml`:
```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.