uv 实战:Python 包构建与分发
内容提要
本文介绍用 uv 开发 Python 库的完整流程:以 universal-add 为例,用 `uv init --package` 创建项目,配置 pyproject.toml 的 build-system 和 scripts,用 click 实现命令行加法工具,并通过 `uv tool install` 全局安装;再用 pypiserver 搭建私有 PyPI,用 `uv build` 构建 wheel 和源码包,用 `uv publish` 上传;最后新建项目用 `--index` 从私有源安装验证,展示 PEP 517/518 下前后端解耦的现代打包体系。
延伸解读
现代打包体系:前后端解耦
文章指出,在 PEP 517 和 PEP 518 标准下,Python 打包流程被解耦为前端和后端。前端负责与用户交互,后端负责生成 Wheel 或源码包。pyproject.toml 中可声明项目使用的后端,且后端工具不必与前端匹配,例如 uv 也可以搭配 poetry-core 后端。这种解耦让开发者能灵活选择工具链,降低了构建门槛。
uv 工具链的完整闭环
从 uv init --package 创建项目,到 uv add 添加依赖、uv tool install 全局安装,再到 uv build 构建、uv publish 上传,uv 覆盖了包开发与分发的全生命周期。文章演示了用 pypiserver 搭建私有 PyPI,并通过 --index 从私有源安装验证,形成本地闭环。整个过程几乎无需关注构建细节,对新手友好。
私有 PyPI 的轻量实践
文章使用 pypiserver 部署简易 PyPI,并强调密码加密需安装 passlib 和指定 bcrypt 版本。通过生成 password.txt 和启动服务,实现了带认证的上传和免认证的下载。这种方式适合测试和内部使用,但文章也提到更成熟的方案如 Sonatype Nexus Repository,可托管和代理官方 PyPI。
Q&A
如何用 uv 创建一个 Python 包项目?
使用命令 `uv init --python ">=3.10" universal-add --package --description "an universal python add package"`,这会创建一个 src 布局的包项目,并生成 pyproject.toml 文件。
pyproject.toml 中 build-system 和 project.scripts 如何配置?
在 pyproject.toml 中,[build-system] 部分指定构建后端,例如 `requires = ["uv_build>=0.10.7,<0.11.0"]` 和 `build-backend = "uv_build"`;[project.scripts] 部分定义命令行入口,例如 `uadd = "universal_add:main"`。
如何用 uv 将本地包安装为全局工具?
在项目目录下运行 `uv tool install . --editable`,即可将包安装为全局工具,并支持代码修改同步。安装后可通过 `uv tool list` 查看,并直接使用命令如 `uadd`。
如何搭建一个简单的私有 PyPI 服务器?
可以使用 pypiserver。先安装:`uv tool install pypiserver[passlib] --with bcrypt==4.0.1`,然后创建密码文件 password.txt,最后启动服务:`pypi-server -P password.txt -p 8082 pypi_data/`。
如何构建并发布 Python 包到私有 PyPI?
在项目目录下运行 `uv build` 生成 wheel 和源码包,然后运行 `uv publish --publish-url=http://127.0.0.1:8082`,按提示输入用户名和密码即可上传。
如何从私有 PyPI 安装包并验证?
新建一个项目,使用 `uv add universal-add --index http://127.0.0.1:8082/simple` 安装包,然后通过 `uv tree` 查看依赖,并用 `uv run python -c 'from universal_add import add; print(add("hello ", "42"))'` 验证功能。