SuperAPI AI 工具集

writing-python-scripts

编程与开发

查看项目

更新于 10-16 08:19

技能介绍

用途

该技能用于指导创建独立的 Python 脚本或单文件自动化工具。资料明确要求:在创建任何独立 Python 脚本或单文件自动化之前,应始终先加载本技能,不要直接编写 Python 脚本。

本技能是 myai 的 engineering-principles 的扩展,需先加载后者;using-my-skills 与 engineering-principles 假定已通过 myai bootstrap 加载。engineering-principles 提供与语言无关的工程哲学,本技能只覆盖 Python 特有的脚本模式:PEP 723 内联元数据、uv run --script、typer CLI 以及单文件约定。

主要能力与约定

单文件脚本使用 PEP 723 内联元数据声明依赖,并通过 uv run --script 执行。writing-python-code 中的全部类型安全与错误处理规则同样适用。

何时使用单脚本(PEP 723)而非完整项目,资料给出的判断依据包括:

  • 单脚本:一个任务一个文件;不需要测试;用于模板化、生成或自动化;可直接运行 ./script.py;依赖写在脚本头部;约 500 行以内。
  • 完整项目:多个功能;需要测试;带 UI 或 API 的应用;通过 uv run poe app 运行;依赖写在 pyproject.toml;会增长到约 500 行以上。

使用方式

目录布局示例:

app/
├── script.py             # Self-contained with inline deps
├── template.html         # Jinja2 templates (if generating text)
├── schema.json           # Validation schema (if validating configs)
├── configs/              # Configuration files (if multiple are needed)
├── pyproject.toml        # Tool config only (ruff, basedpyright)
└── .gitignore

脚本模板(保留原始代码):

#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.14"
# dependencies = [
#     "typer>=0.12.0",
#     "rusty-results>=1.1.1",
#     # Add as needed:
#     # "jinja2>=3.1.0",       # For text output generation
#     # "pyyaml>=6.0.0",       # For YAML config loading
#     # "jsonschema>=4.20.0",  # For config validation
# ]
# ///

import sys
from pathlib import Path
from typing import Final, TypedDict, Required

import typer
from rusty_results import Result, Ok, Err

# =============================================================================
# Constants & Types
# =============================================================================

TEMPLATE_PATH: Final[Path] = Path(__file__).parent / "template.html"

class ItemConfig(TypedDict):
    name: Required[str]
    # ...

# =============================================================================
# Business Logic
# =============================================================================

def load_config(path: Path) -> Result[ItemConfig, str]: ...
def process_item(config: ItemConfig) -> Result[str, str]: ...

# =============================================================================
# CLI Interface
# =============================================================================

app = typer.Typer(help="Description", add_completion=False, context_settings={"help_option_names": ["-h", "--help"]})

@app.command()
def main_command() -> None:
    result = do_work()
    if result.is_err:
        typer.echo(f"Error: {result.unwrap_err()}", err=True)
        sys.exit(1)
    typer.echo(result.unwrap())

if __name__ == "__main__":
    try:
        app()
    except KeyboardInterrupt:
        sys.exit(130)  # No traceback on Ctrl+C

工具配置(pyproject.toml):不需要 [project] 段,只需 ruff 与 basedpyright 配置:

[tool.basedpyright]
pythonVersion = "3.14"
typeCheckingMode = "strict"
reportAny = "error"

[tool.ruff]
line-length = 120
target-version = "py314"

[tool.ruff.lint]
extend-select = ["E", "F", "I", "N", "UP", "S", "B", "A", "C4", "RUF"]
ignore = ["S101", "B008", "RUF001"]

CLI 说明:所有使用 uv 的脚本都应使用 typer。仅当脚本必须在没有任何外部依赖的情况下运行(仅标准库、不使用 uv)时,才使用 argparse。始终向 typer.Typer() 传入 context_settings={"help_option_names": ["-h", "--help"]},因为 typer 默认只支持 --help,而用户期望 -h 也能工作。

Ctrl+C 处理:脚本在 Ctrl+C 时不得输出 traceback。上述模板入口捕获 KeyboardInterrupt 并以退出码 130 退出(Unix 约定:128 + 信号 2)。如果脚本会派生子进程,应始终使用 start_new_session=True,以便 Ctrl+C 能终止整个进程树;子进程关闭模式参见 setting-up-python-projects 技能。

适用场景

适用于一次性任务、模板化与文本生成、配置校验、单文件自动化等场景,尤其是脚本规模在约 500 行以内、无需测试的情况。

限制与相关技能

当脚本增长到约 500 行以上并需要完整项目布局时,应改用 setting-up-python-projects 技能。相关技能还包括:engineering-principles(父技能,与语言无关的哲学)、writing-python-code(Python 特有编码规则,同样适用于脚本,涵盖类型系统、错误处理、异步模式)。

关于收费、价格、平台支持范围等具体信息,资料暂未提供。