MANIFEST.in
MANIFEST.in 就像是打包时的“文件白名单”,明确告诉 setuptools:“这些文件也要打包进去!”
setuptools 默认只会打包 Python 源代码(.py 文件)和 package_data 中明确指定的内容。
如果你有一些非 Python 文件(例如 .proto 文件、模型、配置文件等)需要被打包进发布的安装包,就需要用 MANIFEST.in 显式指定。
# 包含 README 和 LICENSE 文件
include README.md
include LICENSE# 包含某个子目录下所有 .pyd 文件
recursive-include pac/generated *.pyd# 包含所有生成的 .py 和 .pyi 文件
recursive-include pac/generated *.py *.pyi# 包含某个目录及其子目录下的所有文件
recursive-include my_package/static *# 排除某些文件
exclude tests/*
MANIFEST.in 只影响 sdist(源码发布包,.tar.gz)的构建内容;
若要确保文件安装后可用,还需要配合 setup.py 中设置:
include_package_data=True # 告诉 setup() 去读取 MANIFEST.in
setup.py
setup.py 是 Python 项目打包与分发的核心配置脚本,它告诉 setuptools 或 pip:
“我这个项目叫什么?版本是多少?依赖哪些库?哪些文件要打包进去?安装时要执行哪些动作?”
from setuptools import setup, find_namespace_packagessetup(name='my_project', # 包名称,安装后通过 pip list 可看到version='1.0.0', # 版本号author='Your Name', # 作者信息author_email='your.email@example.com', # 作者邮箱description='A powerful Python package for optimization tasks', # 包的简短描述long_description=open('README.md', encoding='utf-8').read(), # 从 README.md 读取长描述(会显示在 PyPI 上)long_description_content_type='text/markdown', # 长描述是 markdown 格式url='https://github.com/yourname/my_project', # 项目主页(例如 GitHub)license='MIT', # 使用的开源协议python_requires='>=3.9', # 要求 Python 版本至少为 3.9package_dir={'': 'src'}, # 指定源码目录是 src/packages=find_namespace_packages(where='src'), # 自动查找所有命名空间包,例如 src/my_package, src/my_package.submodule 等include_package_data=True, # 包含非 .py 文件(前提是 MANIFEST.in 配置正确)# 项目的依赖项,会自动通过 pip 安装install_requires=['numpy>=1.24','scipy>=1.10','grpcio>=1.62.1',],# 命令行入口点配置,例如安装后可使用命令行:myclientry_points={'console_scripts': ['mycli=my_package.cli:main', # mycli 命令会调用 my_package/cli.py 中的 main 函数],},# 分类信息,用于 PyPI 显示和搜索优化classifiers=['Development Status :: 5 - Production/Stable','Intended Audience :: Developers','License :: OSI Approved :: MIT License','Programming Language :: Python :: 3','Programming Language :: Python :: 3.10','Operating System :: OS Independent',],
)
find_namespace_packages() 适用于使用命名空间包结构(即没有 init.py 或分层的包结构);
如果用的是普通包(每层目录有 init.py),可以用 find_packages()。