Python Single-File Scripts with uv
使用uv开发Python单文件脚本
Expert guidance for creating production-ready, self-contained Python scripts using uv's inline dependency management
(PEP 723).
本指南提供专业指导,教你如何使用uv的内联依赖管理(PEP 723)创建可用于生产环境的独立Python脚本。
Create Your First uv Script
创建你的第一个uv脚本
python
#!/usr/bin/env -S uv run --script
python
#!/usr/bin/env -S uv run --script
requires-python = ">=3.11"
requires-python = ">=3.11"
dependencies = [
dependencies = [
"httpx>=0.27.0",
"httpx>=0.27.0",
"rich>=13.0.0",
"rich>=13.0.0",
import httpx
from rich import print
response = httpx.get("
https://api.github.com")
print(f"[green]Status: {response.status_code}[/green]")
Make it executable:
```bash
chmod +x script.py
./script.py # uv automatically installs dependencies
import httpx
from rich import print
response = httpx.get("
https://api.github.com")
print(f"[green]Status: {response.status_code}[/green]")
设置可执行权限:
```bash
chmod +x script.py
./script.py # uv会自动安装依赖
Convert Existing Script
转换现有脚本
Add inline metadata to existing script
为现有脚本添加内联元数据
./tools/convert_to_uv.py existing_script.py
./tools/convert_to_uv.py existing_script.py
Validate PEP 723 metadata
验证PEP 723元数据
./tools/validate_script.py script.py
./tools/validate_script.py script.py
What is PEP 723?
什么是PEP 723?
PEP 723 defines inline script metadata for Python files:
PEP 723定义了Python文件的内联脚本元数据格式:
requires-python = ">=3.11"
requires-python = ">=3.11"
dependencies = [
dependencies = [
"package>=1.0.0",
"package>=1.0.0",
**Benefits:**
- ✅ Dependencies live with the code
- ✅ No separate `requirements.txt`
- ✅ Reproducible execution
- ✅ Version constraints included
- ✅ Self-documenting
**优势:**
- ✅ 依赖与代码共存
- ✅ 无需单独的`requirements.txt`文件
- ✅ 可复现的执行环境
- ✅ 包含版本约束
- ✅ 自文档化
uv Script Execution Modes
uv脚本执行模式
Mode 1: Inline Dependencies (Recommended for utilities)
python
#!/usr/bin/env -S uv run --script
模式1:内联依赖(推荐用于工具类脚本)
python
#!/usr/bin/env -S uv run --script
dependencies = ["httpx"]
dependencies = ["httpx"]
**Mode 2: Project Mode** (For larger scripts)
```bash
uv run script.py # Uses pyproject.toml
**模式2:项目模式**(适用于较大的脚本)
```bash
uv run script.py # 使用pyproject.toml中的配置
模式3:无依赖
python
#!/usr/bin/env -S uv run
Mode 3: No Dependencies
仅使用标准库
python
#!/usr/bin/env -S uv run
Standard library only
重要反模式:切勿这样做
Critical Anti-Patterns: What NOT to Do
/// script
❌ NEVER Use [tool.uv.metadata]
requires-python = ">=3.11"
[tool.uv.metadata] # ❌ 此写法无效
WRONG - This will cause errors:
**错误信息**:
```text
error: TOML parse error at line 3, column 7
unknown field `metadata`
原因:
不属于PEP 723规范,uv不支持该写法。
正确写法 - 使用Python文档字符串存储元数据:
requires-python = ">=3.11"
requires-python = ">=3.11"
[tool.uv.metadata] # ❌ THIS DOES NOT WORK
dependencies = []
**Error**:
```text
error: TOML parse error at line 3, column 7
unknown field `metadata`
Why:
is not part of PEP 723 and is not supported by uv.
CORRECT - Use Python docstrings for metadata:
"""
用途:测试自动化
团队:DevOps
作者:team@example.com
"""
**支持的`tool.uv`字段**(如有需要):
```python
requires-python = ">=3.11"
requires-python = ">=3.11"
dependencies = []
dependencies = []
exclude-newer = "2025-01-01T00:00:00Z" # 确保环境可复现
"""
Purpose: Testing automation
Team: DevOps
Author: team@example.com
"""
**Valid `tool.uv` fields** (if needed):
```python
requires-python = ">=3.11"
示例1:集群健康检查器
exclude-newer = "2025-01-01T00:00:00Z" # For reproducibility
查看examples/03-production-ready/check_cluster_health_enhanced.py
当前基础版本:
python
#!/usr/bin/env python3
import subprocess
Real-World Examples from This Repository
需要手动安装依赖
Example 1: Cluster Health Checker
See examples/03-production-ready/check_cluster_health_enhanced.py
Current version (basic):
python
#!/usr/bin/env python3
import subprocess
**使用uv增强后的生产就绪版本**:
```python
#!/usr/bin/env -S uv run --script --quiet
Manual dependency installation required
/// script
requires-python = ">=3.11"
**Enhanced with uv** (production-ready):
```python
#!/usr/bin/env -S uv run --script --quiet
"""
用途:集群健康监控
团队:基础设施部
"""
import typer
from rich.console import Console
from rich.table import Table
requires-python = ">=3.11"
"""
Purpose: Cluster health monitoring
Team: Infrastructure
"""
import typer
from rich.console import Console
from rich.table import Table
查看examples/03-production-ready/ceph_health.py
模式:通过JSON API交互并生成结构化输出
Example 2: CEPH Health Monitor
本仓库中的最佳实践
See examples/03-production-ready/ceph_health.py
Pattern: JSON API interaction with structured output
查看reference/security-patterns.md获取完整安全指南,包括:
- 密钥管理(环境变量、密钥环、Infisical)
- 输入验证
- 依赖安全
- 文件操作安全
- 命令执行安全
Best Practices from This Repository
2. 版本固定策略
See reference/security-patterns.md for complete security guide including:
- Secrets management (environment variables, keyring, Infisical)
- Input validation
- Dependency security
- File operations security
- Command execution security
2. Version Pinning Strategy
/// script
requires-python = ">=3.11"
"httpx>=0.27.0", # 兼容的最低版本
"rich>=13.0.0", # 经过验证的稳定版本
"ansible>=11.1.0", # 匹配项目要求
Following this repository's approach (from
):
**固定级别:**
- `>=X.Y.Z` - 最低版本(灵活性最高)
- `~=X.Y.Z` - 兼容版本(仅接受补丁更新)
- `==X.Y.Z` - 精确版本(限制最严格)
查看[reference/dependency-management.md](reference/dependency-management.md)。
requires-python = ">=3.11"
"httpx>=0.27.0", # Minimum version for compatibility
"rich>=13.0.0", # Known good version
"ansible>=11.1.0", # Match project requirements
**Pinning levels:**
- `>=X.Y.Z` - Minimum version (most flexible)
- `~=X.Y.Z` - Compatible release (patch updates only)
- `==X.Y.Z` - Exact version (most strict)
See [reference/dependency-management.md](reference/dependency-management.md).
文件命名:
bash
check_cluster_health.py # ✅ 描述性强,采用蛇形命名法
validate_template.py # ✅ 以动作导向命名
cluster.py # ❌ 过于笼统
Shebang写法:
python
#!/usr/bin/env -S uv run --script --quiet
3. Team Standards
--quiet参数会抑制uv自身的输出
File naming:
bash
check_cluster_health.py # ✅ Descriptive, snake_case
validate_template.py # ✅ Action-oriented
cluster.py # ❌ Too generic
Shebang pattern:
python
#!/usr/bin/env -S uv run --script --quiet
**文档模板:**
```python
#!/usr/bin/env -S uv run --script
--quiet suppresses uv's own output
/// script
requires-python = ">=3.11"
**Documentation template:**
```python
#!/usr/bin/env -S uv run --script
"""
检查Proxmox集群健康状态
用途:cluster-monitoring
团队:infrastructure
作者:devops@spaceships.work
使用方法:
python check_cluster_health.py [--node NODE] [--json]
示例:
python check_cluster_health.py --node foxtrot
python check_cluster_health.py --json
"""
requires-python = ">=3.11"
"""
Check Proxmox cluster health
Purpose: cluster-monitoring
Team: infrastructure
Author: devops@spaceships.work
Usage:
python check_cluster_health.py [--node NODE] [--json]
Examples:
python check_cluster_health.py --node foxtrot
python check_cluster_health.py --json
"""
遵循本仓库中的Ansible最佳实践:
python
import sys
import subprocess
def run_command(cmd: str) -> str:
"""执行命令并进行适当的错误处理"""
try:
result = subprocess.run(
cmd.split(),
capture_output=True,
text=True,
check=True
)
return result.stdout
except subprocess.CalledProcessError as e:
print(f"错误:命令执行失败:{cmd}", file=sys.stderr)
print(f" {e.stderr}", file=sys.stderr)
sys.exit(1)
except FileNotFoundError:
print(f"错误:未找到命令:{cmd.split()[0]}", file=sys.stderr)
sys.exit(1)
查看patterns/error-handling.md。
4. Error Handling Patterns
5. 测试模式
Following Ansible best practices from this repository:
python
import sys
import subprocess
def run_command(cmd: str) -> str:
"""Execute command with proper error handling"""
try:
result = subprocess.run(
cmd.split(),
capture_output=True,
text=True,
check=True
)
return result.stdout
except subprocess.CalledProcessError as e:
print(f"Error: Command failed: {cmd}", file=sys.stderr)
print(f" {e.stderr}", file=sys.stderr)
sys.exit(1)
except FileNotFoundError:
print(f"Error: Command not found: {cmd.split()[0]}", file=sys.stderr)
sys.exit(1)
See patterns/error-handling.md.
内联测试(适用于简单脚本):
python
#!/usr/bin/env -S uv run --script
5. Testing Patterns
/// script
requires-python = ">=3.11"
Inline testing (for simple scripts):
python
#!/usr/bin/env -S uv run --script
def validate_ip(ip: str) -> bool:
"""验证IP地址格式"""
import re
pattern = r'^(\d{1,3}.){3}\d{1,3}$'
return bool(re.match(pattern, ip))
requires-python = ">=3.11"
def validate_ip(ip: str) -> bool:
"""Validate IP address format"""
import re
pattern = r'^(\d{1,3}.){3}\d{1,3}$'
return bool(re.match(pattern, ip))
if name == "main":
import sys
# 如果传入--test参数则运行测试
if len(sys.argv) > 1 and sys.argv[1] == "--test":
assert validate_ip("192.168.1.1") == True
assert validate_ip("256.1.1.1") == False
print("所有测试通过!")
sys.exit(0)
# 正常执行逻辑
print(validate_ip("192.168.3.5"))
查看[workflows/testing-strategies.md](workflows/testing-strategies.md)。
if name == "main":
import sys
# Run tests if --test flag provided
if len(sys.argv) > 1 and sys.argv[1] == "--test":
assert validate_ip("192.168.1.1") == True
assert validate_ip("256.1.1.1") == False
print("All tests passed!")
sys.exit(0)
# Normal execution
print(validate_ip("192.168.3.5"))
See [workflows/testing-strategies.md](workflows/testing-strategies.md).
查看anti-patterns/when-not-to-use.md获取详细说明。
当出现以下情况时,应使用标准项目而非单文件脚本:
- ❌ 脚本代码超过500行
- ❌ 需要多个模块/文件
- ❌ 需要复杂的配置管理
- ❌ 需要打包/分发
- ❌ 多个脚本共享库代码
- ❌ 开发Web应用或长期运行的服务
示例 - 过于复杂不适合单文件:
When NOT to Use Single-File Scripts
这应该是一个uv项目,而非脚本:
See anti-patterns/when-not-to-use.md for details.
Use a proper project instead when:
- ❌ Script exceeds 500 lines
- ❌ Multiple modules/files needed
- ❌ Complex configuration management
- ❌ Requires packaging/distribution
- ❌ Shared library code across multiple scripts
- ❌ Web applications or long-running services
Example - Too Complex for Single File:
This should be a uv project, not a script:
常见模式
- Configuration management
查看模式指南获取完整示例:
- CLI应用 - Typer、Click、argparse使用模式
- API客户端 - httpx、requests、认证方式
- 数据处理 - Polars、pandas、数据分析
- 系统自动化 - psutil、subprocess、系统管理
See pattern guides for complete examples:
- CLI Applications - Typer, Click, argparse patterns
- API Clients - httpx, requests, authentication
- Data Processing - Polars, pandas, analysis
- System Automation - psutil, subprocess, system admin
yaml
name: Run Health Checks
on:
schedule:
- cron: '0 */6 * * *' # 每6小时执行一次
jobs:
health-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: Check cluster health
run: |
uv run --script tools/check_cluster_health.py --json
env:
PROXMOX_TOKEN: ${{ secrets.PROXMOX_TOKEN }}
CI/CD Integration
GitLab CI
yaml
name: Run Health Checks
on:
schedule:
- cron: '0 */6 * * *' # Every 6 hours
jobs:
health-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: Check cluster health
run: |
uv run --script tools/check_cluster_health.py --json
env:
PROXMOX_TOKEN: ${{ secrets.PROXMOX_TOKEN }}
yaml
cluster-health:
image: ghcr.io/astral-sh/uv:python3.11-bookworm-slim
script:
- uv run --script tools/check_cluster_health.py
only:
- schedules
查看workflows/ci-cd-integration.md。
yaml
cluster-health:
image: ghcr.io/astral-sh/uv:python3.11-bookworm-slim
script:
- uv run --script tools/check_cluster_health.py
only:
- schedules
See workflows/ci-cd-integration.md.
Tools Available
验证PEP 723元数据
./tools/validate_script.py script.py
Validate PEP 723 metadata
输出:
./tools/validate_script.py script.py
✓ Python version specified
✓ Dependencies properly formatted
Script Conversion
将基于requirements.txt的脚本转换为uv格式
./tools/convert_to_uv.py old_script.py
Convert requirements.txt-based script to uv
生成:
- 包含内联依赖的old_script_uv.py
./tools/convert_to_uv.py old_script.py
- old_script_uv.py with inline dependencies
- Preserves original script
Progressive Disclosure
参考文档
- PEP 723规范 - 完整的内联元数据规范
- 依赖管理 - 版本固定策略
- 安全模式 - 密钥管理、验证、输入清理
Reference Documentation
模式指南
- PEP 723 Specification - Complete inline metadata spec
- Dependency Management - Version pinning strategies
- Security Patterns - Secrets, validation, input sanitization
- CLI应用 - Typer、Click、argparse使用模式
- API客户端 - httpx、requests、认证方式
- 数据处理 - Polars、pandas、数据分析
- 系统自动化 - psutil、subprocess、系统管理
- 错误处理 - 异常处理、日志
注意: 可通过上方的
常见模式部分快速访问这些指南。
- CLI Applications - Typer, Click, argparse patterns
- API Clients - httpx, requests, authentication
- Data Processing - Polars, pandas, analysis
- System Automation - psutil, subprocess, system admin
- Error Handling - Exception handling, logging
Note: See
Common Patterns section above for quick access to these guides.
- NetBox API客户端 - 生产就绪的API客户端,集成Infisical、验证、错误处理和Rich输出
- 集群健康检查器 - 生产就绪的监控脚本,集成Typer、Rich和JSON输出
- NetBox API Client - Production-ready API client with Infisical, validation, error handling, and Rich output
- Cluster Health Checker - Production-ready monitoring script with Typer, Rich, and JSON output
- 何时不使用 - 你需要标准项目的信号
- 常见错误 - 陷阱及规避方法
- When NOT to Use - Signs you need a proper project
- Common Mistakes - Pitfalls and how to avoid them
- 团队采用 - 在团队中推广uv脚本
- CI/CD集成 - GitHub Actions、GitLab CI
- 测试策略 - 内联测试、pytest集成
- Team Adoption - Rolling out uv scripts across teams
- CI/CD Integration - GitHub Actions, GitLab CI
- Testing Strategies - Inline tests, pytest integration
- Ansible最佳实践 - 许多Ansible模块可转换为独立uv脚本
- Proxmox基础设施 - 验证工具采用此模式
- NetBox + PowerDNS集成 - API交互脚本
- Ansible Best Practices - Many Ansible modules could be standalone uv scripts
- Proxmox Infrastructure - Validation tools use this pattern
- NetBox + PowerDNS Integration - API interaction scripts
#!/usr/bin/env -S uv run --script
Standard script execution
静默模式(抑制uv输出)
#!/usr/bin/env -S uv run --script
#!/usr/bin/env -S uv run --script --quiet
Quiet mode (suppress uv output)
指定Python版本
#!/usr/bin/env -S uv run --script --quiet
#!/usr/bin/env -S uv run --script --python 3.11
#!/usr/bin/env -S uv run --script --python 3.11
"typer>=0.9.0" # 现代CLI框架
"click>=8.0.0" # 替代CLI框架
"rich>=13.0.0" # 富文本与格式化
"typer>=0.9.0" # Modern CLI framework
"click>=8.0.0" # Alternative CLI framework
"rich>=13.0.0" # Rich text and formatting
"httpx>=0.27.0" # 现代异步HTTP客户端
"requests>=2.31.0" # 传统HTTP客户端
"httpx>=0.27.0" # Modern async HTTP client
"requests>=2.31.0" # Traditional HTTP client
"polars>=0.20.0" # 高性能数据框库
"pandas>=2.0.0" # 传统数据框库
"polars>=0.20.0" # Fast dataframe library
"pandas>=2.0.0" # Traditional dataframe library
"ansible>=11.1.0" # 自动化工具(来自本仓库)
"infisical-python>=2.3.3" # 密钥管理工具(来自本仓库)
"ansible>=11.1.0" # Automation (from this repo)
"infisical-python>=2.3.3" # Secrets (from this repo)
"psutil>=5.9.0" # System monitoring
python
#!/usr/bin/env -S uv run --script --quiet
Metadata Template
/// script
requires-python = ">=3.11"
python
#!/usr/bin/env -S uv run --script --quiet
"""
单行描述
用途:说明用途
团队:团队名称
作者:email@example.com
使用方法:
python script.py [OPTIONS]
示例:
python script.py --help
"""
requires-python = ">=3.11"
"""
One-line description
Purpose: describe-purpose
Team: team-name
Author: email@example.com
Usage:
python script.py [OPTIONS]
Examples:
python script.py --help
"""
- 始终指定Python版本 -
requires-python = ">=3.11"
- 合理固定依赖版本 - 工具类脚本使用
- 在文档字符串中添加元数据 - 将团队信息、用途和作者信息放在模块文档字符串中
- 添加完整的文档字符串 - 说明用途、使用方法和示例
- 优雅处理错误 - 使用try/except并给出清晰提示
- 验证输入 - 处理前检查参数
- 使用静默模式 - 生产脚本添加参数
- 保持聚焦 - 单文件实现单一功能
- 内联测试 - 添加参数进行简单验证
- 安全管理密钥 - 切勿硬编码,使用环境变量或密钥环
- Always specify Python version -
requires-python = ">=3.11"
- Pin dependencies appropriately - Use for utilities
- Add metadata in docstrings - Put team info, purpose, and author in module docstring
- Include comprehensive docstrings - Document purpose, usage, and examples
- Handle errors gracefully - Use try/except with clear messages
- Validate inputs - Check arguments before processing
- Use quiet mode - flag for production scripts
- Keep it focused - Single file, single purpose
- Test inline - Add flag for simple validation
- Secure secrets - Never hardcode, use env vars or keyring