什么是 MANIFEST.in
MANIFEST.in 是 Python 项目打包时的文件包含/排除配置文件 ,用于告诉 setuptools/distutils:在生成源码包(sdist)时,哪些文件/目录需要被包含,哪些需要被排除。
核心背景:
setuptools默认只会打包 Python 代码文件(.py)和pyproject.toml/setup.cfg等配置文件,但项目中的 README、LICENSE、数据文件、静态资源等不会被自动包含,此时需要用MANIFEST.in显式声明。
基本语法
MANIFEST.in 由一行行指令 组成,指令格式:指令 路径/模式(指令大小写不敏感,路径支持通配符)。
核心指令(常用)
| 指令 | 作用 | 示例 |
|---|---|---|
include |
包含指定文件/目录 | include README.md LICENSE |
exclude |
排除指定文件/目录 | exclude .gitignore *.pyc |
recursive-include |
递归包含指定目录下的匹配文件 | recursive-include src *.py |
recursive-exclude |
递归排除指定目录下的匹配文件 | recursive-exclude tests *.log |
global-include |
从项目根目录递归包含匹配文件 | global-include *.toml |
prune |
排除整个目录(递归) | prune build dist .venv |
通配符规则
*:匹配任意字符(不含路径分隔符/)**:匹配任意字符(含路径分隔符,递归)?:匹配单个字符[abc]:匹配 a/b/c 中的任意一个
完整示例
假设项目结构如下:
my_project/
├── src/
│ ├── my_app/
│ │ ├── __init__.py
│ │ └── utils.py
│ └── data/
│ ├── config.yaml
│ └── logo.png
├── tests/
│ ├── test_utils.py
│ └── logs/
├── README.md
├── LICENSE
├── .gitignore
└── pyproject.toml
对应的 MANIFEST.in:
ini
# 包含根目录的关键文件
include README.md LICENSE pyproject.toml
# 递归包含 src 下的 Python 代码和数据文件
recursive-include src *.py *.yaml *.png
# 包含 tests 下的测试代码,但排除 logs 目录
recursive-include tests *.py
recursive-exclude tests logs *
# 排除无用文件/目录
exclude .gitignore *.pyc *.pyo
prune build dist .venv .git
# 全局排除所有 __pycache__ 目录
recursive-exclude **/__pycache__ *
关键注意事项
-
作用范围 :仅影响源码包(sdist),不影响 wheel 包!
-
wheel 包的文件包含需在
pyproject.toml中通过[tool.setuptools.package-data]或[tool.setuptools.data-files]配置; -
示例(pyproject.toml 中配置 wheel 包的静态文件):
toml[tool.setuptools.package-data] # 给 my_app 包添加数据文件 "my_app" = ["data/*.yaml", "data/*.png"]
-
-
优先级 :
exclude/prune指令优先级高于include,即先包含再排除。 -
验证打包内容 :
生成源码包后,可解压查看是否包含预期文件,或用以下命令预览:
bash# 安装 setuptools pip install setuptools # 预览要打包的文件(不实际生成包) python setup.py sdist --dry-run --manifest-only -
与 pyproject.toml 的配合 :
现代 Python 项目中,
MANIFEST.in通常和pyproject.toml配合使用:pyproject.toml:配置项目元信息、依赖、wheel 包文件;MANIFEST.in:配置 sdist 包的文件包含/排除。
常见错误与避坑
- ❌ 错误:用
include src/data想包含目录 → 正确:recursive-include src/data *(include仅匹配文件,不递归); - ❌ 错误:未排除
__pycache__→ 打包后源码包包含无用的.pyc文件; - ❌ 错误:依赖
MANIFEST.in配置 wheel 包 → wheel 包需单独配置。
总结
MANIFEST.in是 Python 打包时控制源码包(sdist) 文件包含/排除的配置文件,核心指令有include/exclude/recursive-include/prune;- 它仅影响 sdist 包,wheel 包的文件需在
pyproject.toml中通过package-data配置; - 编写时建议用通配符和递归指令,同时排除无用文件(如
__pycache__、dist),保证打包产物精简。