打包与发布
依赖与环境
import失败:包不在搜索路径pip install的四步:查索引、选产物、解依赖、落盘- PyPI 与各语言的包索引
- 传递依赖:
requests与urllib3 - 依赖冲突与「依赖地狱」
- 版本区间求交集的判定
python -m venv venvsource venv/bin/activate只改$PATHwhich python与which pip的前后变化deactivate是 Shell 函数而非程序- 每个项目一个环境
- 系统自带的 Python 不要动
uv venv --python 3.12uv pip install与pip同接口- PEP 517、PEP 621 的规范分层
pyproject.toml取代setup.py与requirements.txt
构建产物与打包
- 库、命令行工具、Web 服务的交付形态
- 换目录后
import失败的根因 - Python 的模块搜索路径
- wheel:带固定目录结构的 zip
- sdist:源码分发包
.tar.gz pyproject.toml的[project]段dependencies声明运行期依赖[project.scripts]生成命令行入口[build-system]与build-backenduv build产出dist/unzip -l检查 wheel 内容dist-info/里的METADATA与RECORD- 平台标签
cp312-cp312-macosx_14_0_arm64 py3-none-any代表跨平台纯 Python- 装源码要编译器,装二进制要匹配平台
ripgrepreleases 的预编译矩阵
发布与版本号
- 开发是连续的,发布是离散的
- dev、staging、prod 的边界
- 一次发布包含的步骤
- 版本号标识某一时刻的行为
- patch、minor、breaking change
- changelog 与 release notes 的分工
- SemVer:
MAJOR.MINOR.PATCH 0.y.z期间接口不承诺稳定uv tree查看整棵依赖树- PEP 440 的版本约束语法
==、>=、>=1.24,<2.0~=2.1.0等价于>=2.1.0,<2.2.0~=与 npm、cargo 的^- 预发布版本
1.0.0rc1 - CalVer:Ubuntu 的
24.04 - 语义化版本也会被违反
可复现构建
- 钉版本(pinning)与范围约束
- 锁文件记录解算后的精确版本
uv lock与uv.lock- 锁文件里的
sha256校验和 uv sync --locked拒绝漂移- 库用范围、应用用精确
- 构建环境本身也是输入
- 编译器、系统库、驱动版本
- Nix、Bazel 的 hermetic build
- 内容寻址与逐位一致
SOURCE_DATE_EPOCH固定时间戳- CI 里对新版本依赖跑测试
- Dependabot 自动提升级 PR
- 升级失败时的回滚预案
pip freeze不是真正的锁文件
虚拟机与容器
- 包管理器管不到的系统依赖
- GPU 驱动、
libpq、OpenSSL - VM 虚拟整台机器,自带内核
- 容器共享宿主内核,更轻更快
- Docker 与 containerd 的分层
docker run -it python:3.12 python- image 是产物,container 是实例
- 镜像分层与构建缓存
FROM python:3.12-slim的意义- 合并
RUN与清理apt缓存 COPY --from=...的 builder 模式linux/amd64与linux/arm64不可互换- macOS 上 Docker 跑在轻量 VM 里
- 容器隔离弱于 VM
- 别用 root 跑、别把密钥烤进层
配置与密钥
- 配置在运行时注入,不写死在代码里
- 环境变量:
os.environ.get - 配置文件:
config.yaml - 默认值与必填项的写法
- 同一份代码部署到多个环境
- 只改配置、不改代码
- 启动即校验,失败就退出
- 密钥不进版本控制
.env、.env.example与.gitignore- 优先级:flag 高于环境变量高于文件
- 容器里的环境变量传递
- 密钥轮换与最小权限
服务与编排
- 单体与微服务的取舍
- Redis、Memcached 当独立服务用
- 服务之间走 HTTP API
docker-compose.yml声明多容器depends_on只管启动顺序- healthcheck 才管服务可用
- Docker 内建 DNS:服务名即主机名
volumes持久化数据docker compose up -d与logs -frestart策略与开机自启- systemd 拉起 compose
- Kubernetes 的适用规模
curl直接调 HTTP API
发布与分发
- 最简单的分发:HTTP 目录列表
- GitHub Releases 附上预编译产物
pip install git+https://...@v2.32.3- 直接从 release URL 装 wheel
- Go 的去中心化模块分发
- 中央索引:PyPI、crates.io、npm
uv publish上传产物- TestPyPI 演练发布流程
--index-url从测试源安装- 校验和与包签名
- PyPI 版本号不可复用
- 私有 registry 与制品库
- Docker Hub 与
ghcr.io - 域名、DNS 与反向代理
- GitHub Pages 托管静态站点
容易混淆的问题
- 虚拟环境和容器解决的是同一件事吗
pip install与uv pip install装到哪- wheel 和 sdist 应该发哪个
~=与^是一回事吗- 锁文件和
requirements.txt差在哪 - image 与 container 有何不同
depends_on能保证依赖服务就绪吗- 库和应用为什么对版本约束态度相反
- 容器里的
localhost指向谁 - 退出容器后数据去哪了