现代Python工具配置Skill modern-python

这个技能用于配置Python项目使用现代工具链,包括uv进行依赖管理、ruff进行代码检查和格式化、ty进行类型检查等。适用于创建新项目、设置开发工具、编写脚本以及从传统工具如pip、Poetry迁移。关键词:Python开发, 项目配置, uv工具, ruff代码检查, ty类型检查, 最佳实践。

DevOps 0 次安装 0 次浏览 更新于 3/14/2026

name: modern-python description: 使用现代工具(uv、ruff、ty)配置Python项目。适用于创建项目、编写独立脚本或从pip/Poetry/mypy/black迁移。

现代Python

基于trailofbits/cookiecutter-python的现代Python工具和最佳实践指南。

何时使用此技能

  • 创建新的Python项目或包
  • 设置pyproject.toml配置
  • 配置开发工具(代码检查、格式化、测试)
  • 使用外部依赖编写Python脚本
  • 从传统工具迁移(当用户请求时)

何时不使用此技能

  • 用户希望保留传统工具:如果明确请求,尊重现有工作流程
  • 需要Python < 3.11:这些工具针对现代Python版本
  • 非Python项目:混合代码库中Python不是主要语言的情况

需要避免的反模式

避免 使用替代
[tool.ty] python-version [tool.ty.environment] python-version
uv pip install uv adduv sync
手动编辑pyproject.toml添加依赖 uv add <pkg> / uv remove <pkg>
hatchling 构建后端 uv_build(更简单,适用于大多数情况)
Poetry uv(更快、更简单、更好的生态系统集成)
requirements.txt 脚本使用PEP 723,项目使用pyproject.toml
mypy / pyright ty(更快,来自Astral团队)
[project.optional-dependencies] 用于开发工具 [dependency-groups](PEP 735)
手动虚拟环境激活(source .venv/bin/activate uv run <cmd>
pre-commit prek(更快,无需Python运行时)

关键原则:

  • 始终使用uv adduv remove管理依赖
  • 永远不要手动激活或管理虚拟环境——对所有命令使用uv run
  • 使用[dependency-groups]用于开发/测试/文档依赖,而不是[project.optional-dependencies]

决策树

你在做什么?
│
├─ 具有依赖的单文件脚本?
│   └─ 使用PEP 723内联元数据(./references/pep723-scripts.md)
│
├─ 新的多文件项目(不发布)?
│   └─ 最小uv设置(见下面的快速开始)
│
├─ 新的可重用包/库?
│   └─ 完整项目设置(见下面的完整设置)
│
└─ 迁移现有项目?
    └─ 见下面的迁移指南

工具概述

工具 目的 替代
uv 包/依赖管理 pip, virtualenv, pip-tools, pipx, pyenv
ruff 代码检查和格式化 flake8, black, isort, pyupgrade, pydocstyle
ty 类型检查 mypy, pyright(更快替代)
pytest 测试覆盖 unittest
prek 预提交钩子(设置 pre-commit(更快,Rust原生)

安全工具

工具 目的 何时运行
shellcheck Shell脚本检查 预提交
detect-secrets 秘密检测 预提交
actionlint 工作流程语法验证 预提交, CI
zizmor 工作流程安全审计 预提交, CI
pip-audit 依赖漏洞扫描 CI, 手动
Dependabot 自动依赖更新 计划任务

security-setup.md获取配置和使用。

快速开始:最小项目

对于不打算发布的简单多文件项目:

# 使用uv创建项目
uv init myproject
cd myproject

# 添加依赖
uv add requests rich

# 添加开发依赖
uv add --group dev pytest ruff ty

# 运行代码
uv run python src/myproject/main.py

# 运行工具
uv run pytest
uv run ruff check .

完整项目设置

如果从零开始,询问用户是否更愿意使用Trail of Bits的cookiecutter模板来引导一个已预配置工具的完整项目。

uvx cookiecutter gh:trailofbits/cookiecutter-python

1. 创建项目结构

uv init --package myproject
cd myproject

这会创建:

myproject/
├── pyproject.toml
├── README.md
├── src/
│   └── myproject/
│       └── __init__.py
└── .python-version

2. 配置pyproject.toml

pyproject.md获取完整配置参考。

关键部分:

[project]
name = "myproject"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = []

[dependency-groups]
dev = [{include-group = "lint"}, {include-group = "test"}, {include-group = "audit"}]
lint = ["ruff", "ty"]
test = ["pytest", "pytest-cov"]
audit = ["pip-audit"]

[tool.ruff]
line-length = 100
target-version = "py311"

[tool.ruff.lint]
select = ["ALL"]
ignore = ["D", "COM812", "ISC001"]

[tool.pytest]
addopts = ["--cov=myproject", "--cov-fail-under=80"]

[tool.ty.terminal]
error-on-warning = true

[tool.ty.environment]
python-version = "3.11"

[tool.ty.rules]
# 新项目从第一天起就严格
possibly-unresolved-reference = "error"
unused-ignore-comment = "warn"

3. 安装依赖

# 安装所有依赖组
uv sync --all-groups

# 或安装特定组
uv sync --group dev

4. 添加Makefile

.PHONY: dev lint format test build

dev:
	uv sync --all-groups

lint:
	uv run ruff format --check && uv run ruff check && uv run ty check src/

format:
	uv run ruff format .

test:
	uv run pytest

build:
	uv build

迁移指南

当用户请求从传统工具迁移时:

从requirements.txt + pip

首先,确定代码性质:

对于独立脚本:转换为PEP 723内联元数据(见pep723-scripts.md

对于项目

# 在现有项目中初始化uv
uv init --bare

# 使用uv添加依赖(不通过编辑pyproject.toml)
uv add requests rich  # 添加每个包

# 或从requirements.txt导入(在添加前审查每个包)
# 注意:复杂版本说明符可能需要手动处理
grep -v '^#' requirements.txt | grep -v '^-' | grep -v '^\s*$' | while read -r pkg; do
    uv add "$pkg" || echo "添加失败: $pkg"
done

uv sync

然后:

  1. 删除requirements.txtrequirements-dev.txt
  2. 删除虚拟环境(venv/.venv/
  3. uv.lock添加到版本控制

从setup.py / setup.cfg

  1. 运行uv init --bare创建pyproject.toml
  2. 使用uv add添加来自install_requires的每个依赖
  3. 使用uv add --group dev添加开发依赖
  4. 将非依赖元数据(名称、版本、描述等)复制到[project]
  5. 删除setup.pysetup.cfgMANIFEST.in

从flake8 + black + isort

  1. 通过uv remove移除flake8、black、isort
  2. 删除.flake8pyproject.toml [tool.black][tool.isort]配置
  3. 添加ruff:uv add --group dev ruff
  4. 添加ruff配置(见ruff-config.md
  5. 运行uv run ruff check --fix .应用修复
  6. 运行uv run ruff format .格式化

从mypy / pyright

  1. 通过uv remove移除mypy/pyright
  2. 删除mypy.inipyrightconfig.json[tool.mypy]/[tool.pyright]部分
  3. 添加ty:uv add --group dev ty
  4. 运行uv run ty check src/

快速参考:uv命令

命令 描述
uv init 创建新项目
uv init --package 创建可发布包
uv add <pkg> 添加依赖
uv add --group dev <pkg> 添加到依赖组
uv remove <pkg> 移除依赖
uv sync 安装依赖
uv sync --all-groups 安装所有依赖组
uv run <cmd> 在venv中运行命令
uv run --with <pkg> <cmd> 使用临时依赖运行
uv build 构建包
uv publish 发布到PyPI

使用--with的临时依赖

对于需要项目中不存在的包的一次性命令,使用uv run --with

# 使用临时包运行Python
uv run --with requests python -c "import requests; print(requests.get('https://httpbin.org/ip').json())"

# 使用临时依赖运行模块
uv run --with rich python -m rich.progress

# 多个包
uv run --with requests --with rich python script.py

# 结合项目依赖(添加到现有venv)
uv run --with httpx pytest  # 项目依赖 + httpx

何时使用--with vs uv add

  • uv add:包是项目依赖(放入pyproject.toml/uv.lock)
  • --with:一次性使用、测试或项目上下文外的脚本

uv-commands.md获取完整参考。

快速参考:依赖组

[dependency-groups]
dev = ["ruff", "ty"]
test = ["pytest", "pytest-cov", "hypothesis"]
docs = ["sphinx", "myst-parser"]

安装:uv sync --group dev --group test

最佳实践检查清单

  • [ ] 对包使用src/布局
  • [ ] 设置requires-python = ">=3.11"
  • [ ] 配置ruff,select = ["ALL"]并明确忽略
  • [ ] 使用ty进行类型检查
  • [ ] 强制执行测试覆盖最小(80%+)
  • [ ] 使用依赖组而不是extras用于开发工具
  • [ ] 将uv.lock添加到版本控制
  • [ ] 对独立脚本使用PEP 723

下一步阅读