Python包与环境管理工具uv及pyproject.toml指南

文章目录

简介

uv 是一款 Rust 编写的 Python 包和环境管理工具,速度极快

  • 比 pip 快 10-100倍,使用 Rust 编写,并行下载
  • 一个工具替代多个工具,提供依赖管理、虚拟环境创建、Python 版本管理等一站式服务
  • 完全兼容 pip 和 requirements.txt
  • 支持 Windows/macOS/Linux

安装

Windows

shell 复制代码
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

macOS/Linux

shell 复制代码
curl -LsSf https://astral.sh/uv/install.sh | sh

pip

shell 复制代码
pip install uv

更新

shell 复制代码
uv self update

初试

初始化项目,会创建:

shell 复制代码
uv init example

添加依赖

shell 复制代码
uv add ruff

检查代码质量

shell 复制代码
uv run ruff check

生成/更新锁文件,锁定依赖版本

shell 复制代码
uv lock

根据锁文件同步安装所有依赖,类似于 pip install -r requirements.txt

shell 复制代码
uv sync

如果安装太慢,可以在 pyproject.toml 设置国内镜像源

tool.uv

index-url = "https://pypi.tuna.tsinghua.edu.cn/simple"

常用命令

Python版本

shell 复制代码
# 查看可用Python版本
uv python list

# 安装特定版本Python
uv python install 3.12

# 设置全局默认版本
uv python default 3.12

运行脚本

example.py

python 复制代码
import sys

print(" ".join(sys.argv[1:]))
shell 复制代码
uv run example.py hello world!

虚拟环境

shell 复制代码
# 创建虚拟环境
uv venv

# 指定Python版本
uv venv --python 3.11

# Windows激活虚拟环境
.venv\Scripts\activate

# macOS/Linux激活虚拟环境
source .venv/Scripts/activate

包管理

shell 复制代码
# 安装最新版本
uv pip install requests

# 安装指定版本
uv pip install requests==2.31.0

# 从requirements.txt安装
uv pip install -r requirements.txt

# 安装包到开发环境
uv add --dev pytest

# 卸载包
uv pip uninstall requests
uv remove requests

# 更新包
uv lock --upgrade-package requests

如何使用uv更新项目依赖

使用工具

无需安装直接调用工具

shell 复制代码
uvx ruff

如果该工具经常用,可以安装,uv 会自动添加到环境变量 Path 的 bin 目录下,然后就可以直接调用了

shell 复制代码
uv tool install ruff

ruff --version

更新工具

shell 复制代码
uv tool upgrade ruff

TODO:项目管理

shell 复制代码
# 初始化新项目
uv init example
cd example

# 初始化已有项目
uv init

pyproject.toml

项目的元数据,包括依赖项

toml 复制代码
[project]
name = "example"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
dependencies = []

官方 pyproject.toml 指南

.python-version

默认 Python 版本

venv

虚拟环境

uv.lock

跨平台的锁文件,包含项目依赖项的详细信息,与指定项目大致需求的 pyproject.toml 文件不同,该锁文件包含了项目环境中实际安装的精确版本号,以便在不同机器上实现一致且可重复的安装

应该由 uv 管理,不应手动编辑

发布包

<>

<>

shell 复制代码

<>

shell 复制代码

pyproject.toml

pyproject.toml 是 Python 项目的总配置文件,替代 setup.py、requirements.txt、setup.cfg 等多个文件,一个文件搞定所有配置

toml 复制代码
[build-system]                   # 构建系统
[project]                        # 项目元数据
[project.dependencies]           # 主依赖
[project.optional-dependencies]  # 可选依赖
[project.scripts]                # 命令行工具
[tool.poetry]                    # Poetry 配置
[tool.black]                     # Black 代码格式化
[tool.ruff]                      # Ruff linting
[tool.mypy]                      # 类型检查
[tool.pytest.ini_options]        # 测试配置

build-system

构建系统

toml 复制代码
[build-system]
requires = [
    "hatchling",           # 现代构建工具(推荐)
    # "setuptools>=61.0",  # 传统构建工具
    # "poetry-core",       # Poetry 使用
    # "flit_core",         # Flit 使用
    # "pdm-backend",       # PDM 使用
]

# 必填:构建后端
build-backend = "hatchling.build"
# build-backend = "setuptools.build_meta"
# build-backend = "poetry.core.masonry.api"
# build-backend = "flit_core.buildapi"
# build-backend = "pdm.backend"

# 可选:构建后端路径
backend-path = ["backend"]  # 自定义后端位置

project

项目元数据

基本信息

toml 复制代码
[project]
# 1. 项目标识(必填)
name = "my-project"           # 包名,pip install 用的
version = "0.1.0"             # 版本,推荐语义化版本

# 2. 作者和许可证
authors = [
    {name = "张三", email = "zhangsan@example.com"},
    {name = "李四"},
]
maintainers = [                # 维护者(可选)
    {name = "王五", email = "wangwu@example.com"},
]
license = {text = "MIT"}      # 许可证
# 或 license = {file = "LICENSE"}
# 或 license = "MIT"

# 3. 描述(必填)
description = "一个很棒的Python库"
readme = "README.md"          # 或 readme = "README.rst"

# 4. 分类信息
classifiers = [               # PyPI分类,见 https://pypi.org/classifiers/
    "Development Status :: 4 - Beta",
    "Intended Audience :: Developers",
    "Topic :: Software Development :: Libraries",
    "License :: OSI Approved :: MIT License",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
]

# 5. 关键词和项目URLs
keywords = ["ai", "machine-learning", "web"]
urls = {                      # 项目相关链接
    "Homepage" = "https://github.com/username/my-project",
    "Documentation" = "https://my-project.readthedocs.io",
    "Repository" = "https://github.com/username/my-project.git",
    "Bug Tracker" = "https://github.com/username/my-project/issues",
    "Changelog" = "https://github.com/username/my-project/releases",
}

依赖管理

toml 复制代码
[project]
# 1. Python版本要求
requires-python = ">=3.8"           # 最低Python版本
# requires-python = ">=3.8,<3.13"   # 版本范围
# requires-python = "~=3.8"         # 3.8.x 兼容

# 2. 主依赖(安装时必定安装)
dependencies = [
    # 精确版本
    "requests==2.31.0",
    
    # 版本范围
    "pandas>=1.5.0,<2.0.0",      # 1.5.0 ≤ version < 2.0.0
    
    # 兼容版本
    "numpy~=1.24.0",             # >=1.24.0,<1.25.0
    
    # 条件依赖
    'typing-extensions>=4.5.0;python_version<"3.10"',  # Python<3.10才需要
    
    # 环境标记
    'pywin32>=300;sys_platform=="win32"',  # 仅Windows
    'pytest>=7.0; extra == "dev"',          # 仅dev环境
    
    # URL依赖
    "mypackage @ https://github.com/user/repo/archive/main.tar.gz",
    "otherpackage @ git+https://github.com/user/other.git@main",
    
    # 本地路径
    "localpackage @ file:///path/to/local/package",
    "relativepackage @ file://./local/relative/path",
]

# 3. 可选依赖(分组)
[project.optional-dependencies]
# 开发依赖
dev = [
    "pytest>=7.0.0",
    "pytest-cov>=4.0.0",
    "black>=23.0.0",
    "ruff>=0.1.0",
    "mypy>=1.0.0",
    "pre-commit>=3.0.0",
]

# 测试依赖
test = [
    "pytest",
    "pytest-asyncio",
    "pytest-mock",
    "hypothesis",
]

# 文档依赖
docs = [
    "sphinx>=7.0.0",
    "sphinx-rtd-theme>=1.0.0",
    "myst-parser>=2.0.0",
]

# 性能优化依赖
perf = [
    "numba>=0.57.0",
    "pandas[performance]",
]

# 4. 动态版本(从文件读取)
dynamic = ["version"]  # 从 __version__.py 读取

命令行工具

toml 复制代码
[project]
# 1. 控制台脚本
[project.scripts]
# 命令名 = "模块:函数"
"mycli" = "my_package.cli:main"  # 运行: mycli
"convert" = "my_package.tools:convert_file"

# 2. GUI 脚本
[project.gui-scripts]
"myapp" = "my_package.gui:main"

# 3. 插件入口点
[project.entry-points]
# 3.1 控制台脚本分组
"console_scripts" = {
    "mytool" = "mypackage.cli:main",
}

# 3.2 插件系统
"myproject.plugins" = {
    "csv" = "myproject.plugins.csv:CSVPlugin",
    "json" = "myproject.plugins.json:JSONPlugin",
}

# 3.3 测试插件
"pytest11" = {
    "myplugin" = "myproject.pytest_plugin",
}

代码质量和格式化

toml 复制代码
# 1. Black 代码格式化
[tool.black]
line-length = 88
target-version = ['py38', 'py39', 'py310', 'py311', 'py312']
include = '\.pyi?$'
extend-exclude = '''
/(
    \.eggs
  | \.git
  | \.hg
  | \.mypy_cache
  | \.tox
  | \.venv
  | _build
  | buck-out
  | build
  | dist
)/
'''

# 2. Ruff - 极速的 Python linter
[tool.ruff]
target-version = "py38"
line-length = 88
select = [
    "E",   # pycodestyle 错误
    "W",   # pycodestyle 警告
    "F",   # pyflakes
    "I",   # isort
    "B",   # flake8-bugbear
    "C4",  # flake8-comprehensions
    "UP",  # pyupgrade
]
ignore = [
    "E501",  # 行太长,black会处理
    "B008",  # 函数默认参数不要用可变对象
    "C901",  # 函数太复杂
]
exclude = [
    ".git",
    ".mypy_cache",
    ".pytest_cache",
    ".ruff_cache",
    ".venv",
    "__pycache__",
    "build",
    "dist",
]
fix = true
unfixable = ["B", "F401"]

# 3. isort 导入排序
[tool.isort]
profile = "black"
line_length = 88
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true
ensure_newline_before_comments = true

# 4. mypy 类型检查
[tool.mypy]
python_version = "3.8"
warn_return_any = true
warn_unused_configs = true
ignore_missing_imports = true
explicit_package_bases = true
namespace_packages = true
mypy_path = "src"

[[tool.mypy.overrides]]
module = [
    "django.*",
    "sqlalchemy.*",
    "flask.*",
]
ignore_errors = true

测试配置

toml 复制代码
# 1. pytest
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
    "--strict-markers",
    "--strict-config",
    "-v",           # 详细输出
    "--tb=short",   # 简短的traceback
    "--durations=10",  # 显示最慢的10个测试
]
markers = [
    "slow: 运行缓慢的测试",
    "integration: 集成测试",
    "unit: 单元测试",
    "skip: 跳过此测试",
]
filterwarnings = [
    "error",  # 将警告转为错误
    "ignore::DeprecationWarning",  # 忽略某些警告
]

# 2. pytest-cov 覆盖率
[tool.coverage.run]
source = ["src"]
omit = [
    "*/tests/*",
    "*/test_*.py",
    "*/__pycache__/*",
    "*/migrations/*",
]

[tool.coverage.report]
exclude_lines = [
    "pragma: no cover",
    "def __repr__",
    "if self.debug:",
    "if settings.DEBUG",
    "raise AssertionError",
    "raise NotImplementedError",
    "if 0:",
    "if __name__ == .__main__.:",
    "class .*\\bProtocol\\):",
    "@(abc\\.)?abstractmethod",
]
fail_under = 80  # 覆盖率低于80%失败

# 3. pytest-asyncio
[tool.pytest-asyncio]
asyncio_mode = "auto"

包管理工具配置

toml 复制代码
# 1. Poetry
[tool.poetry]
name = "my-project"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]
readme = "README.md"
packages = [{include = "my_package", from = "src"}]

[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.31.0"

[tool.poetry.group.dev.dependencies]
pytest = "^7.4.0"

[tool.poetry.scripts]
my-script = "my_package:main"

# 2. PDM
[tool.pdm]
version = { source = "file", path = "my_package/__version__.py" }
dependencies = [
    "requests>=2.31.0",
    "pandas>=1.5.0",
]

[tool.pdm.dev-dependencies]
dev = [
    "pytest>=7.0.0",
    "black>=23.0.0",
]

# 3. Hatch
[tool.hatch]
version = { path = "my_package/__version__.py" }

[tool.hatch.envs.default]
dependencies = [
    "requests>=2.31.0",
]

[tool.hatch.envs.dev]
dependencies = [
    "pytest",
    "black",
]

[tool.hatch.build.targets.wheel]
packages = ["src/my_package"]

其他工具配置

toml 复制代码
# 1. 提交前检查
[tool.pre-commit.ci]
skip = []
autofix_prs = true
autoupdate_schedule = "monthly"

# 2. 版本管理
[tool.bumpversion]
current_version = "0.1.0"
parse = r'(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)'
serialize = [
    '{major}.{minor}.{patch}',
    '{major}.{minor}',
    '{major}',
]

[tool.bumpversion.file:pyproject.toml]
search = 'version = "{current_version}"'
replace = 'version = "{new_version}"'

[tool.bumpversion.file:src/my_package/__init__.py]
search = '__version__ = "{current_version}"'
replace = '__version__ = "{new_version}"'

# 3. 安全扫描
[tool.bandit]
exclude_dirs = ["tests", "test", "docs"]
skips = ["B101", "B104"]
targets = ["src"]

# 4. 文档生成
[tool.sphinx]
project = "My Project"
author = "Your Name"
version = "0.1.0"
extensions = [
    "sphinx.ext.autodoc",
    "sphinx.ext.napoleon",
    "sphinx.ext.viewcode",
    "myst_parser",
]
html_theme = "sphinx_rtd_theme"

# 5. 任务运行器
[tool.taskipy.tasks]
test = "pytest"
lint = "ruff check ."
format = "black ."
type = "mypy ."
check = ["ruff check .", "mypy .", "pytest"]
clean = "rm -rf build dist *.egg-info .coverage .mypy_cache .pytest_cache .ruff_cache"
toml 复制代码
toml 复制代码

参考文献

  1. uv 官网
  2. uv GitHub
  3. uv 入门教程 --- Python 包与环境管理工具 | 菜鸟教程
  4. 如何使用uv更新项目依赖
  5. <>
  6. <>
  7. <>
  8. <>
  9. <>
  10. <>
  11. <>
相关推荐
CCPC不拿奖不改名2 小时前
Git 核心操作命令
人工智能·git·python·rnn·自然语言处理·josn
历程里程碑2 小时前
哈希1:两数之和:哈希表优化指南
java·开发语言·数据结构·c++·算法·哈希算法·散列表
oioihoii2 小时前
Vibe Coding在QT桌面开发中的可行性分析
开发语言·人工智能·qt
码界奇点2 小时前
Tomcat与JDK版本对照全解析避坑指南生产环境选型建议
java·开发语言·容器·jdk·tomcat
CCPC不拿奖不改名2 小时前
面向计算机应用的数学
人工智能·python·rnn·深度学习·embedding·应用开发数学
董世昌412 小时前
js的数据类型有几类?一共有几种?
开发语言·javascript·ecmascript
被星1砸昏头2 小时前
C++中的状态模式实战
开发语言·c++·算法
Remember_9932 小时前
【数据结构】深入理解排序算法:从基础原理到高级应用
java·开发语言·数据结构·算法·spring·leetcode·排序算法
wanzhong23332 小时前
开发日记13-响应式变量
开发语言·前端·javascript·vue