Python 项目结构与打包
区分 src 布局、pyproject 元数据、构建后端与可编辑安装,并验证最小 CLI 的安装入口。
#concept
#growing
#dev
#python
#python
[!info] related notes
Python 项目结构与打包
这个概念为什么出现
“能跑脚本”不等于“可安装的库/应用”。没有布局约定会出现:测试导入错包、生产缺依赖、工具找不到元数据。
[!abstract] 一句话理解 用清晰目录 +
pyproject.toml声明项目元数据与依赖,通过构建后端打包或可编辑安装进入环境。
最小可运行示例
先把示例放进业务场景,再看代码:
场景:将内部工具安装为可调用命令
最小目录(src/myapp/init.py 为空;实际项目还应有 tests/ 和 README.md):
pyproject.toml
src/myapp/__init__.py
src/myapp/cli.py
pyproject.toml:
[build-system]
requires = ["setuptools>=64"]
build-backend = "setuptools.build_meta"
[project]
name = "tf-layout-demo"
version = "0.1.0"
requires-python = ">=3.10"
[project.scripts]
tf-layout-demo = "myapp.cli:main"
[tool.setuptools.packages.find]
where = ["src"]
src/myapp/cli.py:
def main() -> None:
print("package installed")
在已激活的隔离环境中,从项目根执行:
python -m pip install -e .
tf-layout-demo
期望输出 package installed。开发用可编辑安装;发布前还应构建 wheel 并在干净环境安装验证,避免开发环境掩盖漏打包文件。
结合场景再看三个关注点
- src 布局减少仓库根目录直接遮蔽已安装包的机会,但修改 PYTHONPATH 仍可绕过;不能仅凭布局证明 wheel 正确。
- pyproject 成为现代中心配置。
- 需要 CLI 时用 [project.scripts] 声明 console script;库不必提供命令行入口。
核心概念与准确模型
- 构建后端:setuptools/hatchling/flit 等
- 可编辑安装:python -m pip install -e .;uv sync 默认只在项目配置为可打包/安装时安装项目,—no-editable 可关闭可编辑模式。
- 版本、依赖、脚本入口
- wheel/sdist 产物
边界情况与反直觉行为
- 命名空间包规则不同。
- 多包 monorepo 需工具链支持。
- 资源文件打包要用 package data。
常见误区
[!warning] 常见误区:把 venv 目录提交进 git 错误理解:环境也是源码。
正确模型:锁文件 + 可重建环境。
工程实践
- 单一包名清晰
- CI:install → test → build
- 应用镜像内安装 wheel
本节总结
布局与打包把“一堆 py 文件”变成可协作工件。
自测题
- src 布局的主要收益?
- pyproject 角色?
参考答案
- 默认把源码移出仓库根的直接导入路径,鼓励安装后测试;并非禁止其他路径配置。
- 项目元数据、依赖与工具配置中心。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Packaging User Guide | 指南 | 官方打包 |
| pyproject.toml | 指南 | 元数据 |