文章目录

简介
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
运行脚本
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
使用工具
无需安装直接调用工具
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 = []
.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
参考文献
- uv 官网
- uv GitHub
- uv 入门教程 --- Python 包与环境管理工具 | 菜鸟教程
- 如何使用uv更新项目依赖
- <>
- <>
- <>
- <>
- <>
- <>
- <>