python-packaginglisted
Install: claude install-skill AntheaLaffy/the-missing-semester-skills
# Python 打包与发布
主线:能跑 ≠ 能交付——shipping 是把代码变成「别人不用你的电脑环境也能装」的制品(artifact)。本讲以 Python 为介质讲通用概念:依赖、环境、制品、版本、发布。其他语言工具不同、概念一致:Rust 用 cargo 统一构建/测试/依赖/发布;Python 在规范层统一(PEP 517/621 定义打包接口与 pyproject.toml 元数据,pip/uv、setuptools/hatch/poetry 多工具竞争);LaTeX 发行版(TeX Live/MacTeX)自带几千个包。
## 依赖与环境
- 安装流程(pip/uv):查索引(PyPI)→ 选平台匹配的制品 → 解析传递依赖 → 下载解包落盘。requests 依赖 urllib3/idna/certifi/charset-normalizer——装它之前必须先装这些。
- 依赖冲突 = 依赖地狱:多个包要求同一依赖的互斥版本区间(tensorflow 要 numpy<1.19,另一个包要 >=1.19)→ 无解。解法:每个项目一个虚拟环境,各自隔离。
- venv:`python -m venv venv && source venv/bin/activate`——环境 = 独立的运行时副本 + 自己的包集合。激活后 PATH 指向 venv/bin,`which python`/`which pip` 都变了;`deactivate` 退出。
- uv 优先:与 pip 同接口但快一个量级(`pip install uv` 装上);`uv venv --python 3.12` 还能管理多版本运行时(多版本测试、项目锁版本用)。
- 别改系统自带的 Python 安装——OS 自己的功能可能依赖它;用独立环境。
## 制品与打包
- 源码 vs 制品:开发者读写源码;制品是打包好的可分发产物。Python 只在特定位置找模块(当前目录、已装包、PYTHONPATH)——换个目录 import 就失败,打包 = 把代码装进已知位置。
- pyproject.toml 是清单(manifest):名字、版本、依赖、`[project.scripts]` 声明 CLI 入口、build-system。现代首选;requirements.txt/setup.py 是旧法,兼容但别新建。
- `uv build` 产出两种制品:.whl(wheel,特定结构的 zip:代码 + METADATA/WHEEL/RECORD)与 .tar.gz(sdist 源码发行版,给需要从源码构建的系统)。wheel 文件名编码平台:`py3-none-any` 通用;`cp312-macosx_14_0_arm64` 平台专用(含编译代码的包如 numpy 分平台)。
- 平台相关依赖(CUDA、GPU 驱动等)超出包管理器范围:要分平台分别构建,或依赖系统级安装(见 `containers-deployment`)。
- 安装方式二分:从源码装(要编译器、慢、大项目可能极久)vs 预编译二进制(快,但必须匹配平台/架构,如 ripgrep 的 releases 页)。
## 发布
- 最简发布 = 把制品放上网让人下载(Ubuntu 的包存档本质就是 HTTP 目录下的 .deb 列表)。
- GitHub 是事实平台:Releases 给打 tag 的版本附预编译制品;pip 可直接从 GitHub 装(`git+https://