在现代 Python 开发中,distribute 库已经被 setuptools 完全取代了。

distribute是一个历史项目,它曾是setuptools的一个分支,旨在更快地合并新的特性,大约在 2025 年,setuptools项目吸收了distribute的所有功能,distribute也就停止了更新。setuptools是目前 Python 生态中事实上的标准,用于打包、分发和安装 Python 项目。
当您今天看到关于 distribute 的教程或遗留代码时,几乎可以将其理解为 setuptools,下面我将从 setuptools 的角度来全面讲解如何打包和分发你的 Python 项目。
为什么需要打包和分发?
将你的 Python 代码打包,主要有以下几个目的:
- 代码复用:将你的项目封装成一个库,方便其他开发者通过
pip install来安装和使用。 - 依赖管理:明确声明项目运行所需的依赖项,确保用户安装你的库时能自动安装好所有依赖。
- 版本控制:为你的项目打上版本号,方便用户指定安装特定版本。
- 安装简化:用户无需关心你的项目结构,只需一条命令即可完成安装。
核心概念:PyPI (Python Package Index)
PyPI 是 Python 官方的第三方包仓库,你可以把它想象成 Python 世界的 "App Store",当你把你的包上传到 PyPI 后,任何人都可以通过 pip 安装它。
项目结构
一个标准的可分发的 Python 项目通常有以下结构:

my_project/
├── my_package/ # 你的源代码包
│ ├── __init__.py # 包的初始化文件,可以为空
│ └── my_module.py # 你的核心模块
├── LICENSE # 项目许可证 (如 MIT, Apache 2.0)
├── README.md # 项目说明文档
├── setup.py # **打包配置的核心文件**
├── setup.cfg # setup.py 的配置文件 (可选,推荐)
└── MANIFEST.in # 指定需要包含在包中的非代码文件 (可选)
my_package/: 这是你的源代码包,包名应该简短、小写,并且是唯一的。setup.py: 这是打包的脚本,它包含了关于你包的所有元信息(名称、版本、描述、依赖等)。README.md: 用户在 PyPI 上首先看到的内容,非常重要。LICENSE: 声明你的项目可以被如何使用,这是法律保护。
编写 setup.py 文件
setup.py 是整个打包过程的核心,下面是一个详细的示例,并附有注释解释每个部分。
# my_project/setup.py
from setuptools import setup, find_packages
# 读取 README.md 文件,作为长描述
# 这是一种常见的做法,可以避免在代码中硬编码长文本
with open("README.md", "r", encoding="utf-8") as fh:
long_description = fh.read()
setup(
# --- 1. 基本信息 ---
name="my-awesome-package", # 包名,在 PyPI 上必须唯一
version="0.1.0", # 版本号,遵循语义化版本规范 (MAJOR.MINOR.PATCH)
author="Your Name", # 作者名
author_email="your.email@example.com", # 作者邮箱
description="A small example package", # 简短描述
long_description=long_description, # 详细描述
long_description_content_type="text/markdown", # 声明长描述的格式,Markdown 是标准
url="https://github.com/yourusername/my_project", # 项目主页/仓库地址
# --- 2. 打包配置 ---
packages=find_packages(), # 自动发现所有包 (会找到 'my_package')
# 如果你的项目结构简单,也可以手动指定:
# packages=['my_package'],
python_requires='>=3.6', # 要求 Python 版本不低于 3.6
# --- 3. 依赖项 ---
# install_requires 列出了你的包在运行时依赖的其他库
install_requires=[
'requests',
'numpy>=1.19.0', # 可以指定版本
'pandas~=1.2.0', # ~= 表示兼容性版本 (>=1.2.0, <1.3.0)
],
# --- 4. 可选依赖 (通过 "extras" 提供) ---
# 你可以安装 "my-package[dev]" 来获得开发所需的工具
extras_require={
'dev': [
'pytest',
'flake8',
'black',
],
'test': [
'pytest-cov',
]
},
# --- 5. 项目分类和入口点 ---
classifiers=[
"Development Status :: 3 - Alpha", # 开发状态
"Intended Audience :: Developers", # 目标用户
"Topic :: Software Development :: Build Tools",
"License :: OSI Approved :: MIT License", # 开源许可证
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Operating System :: OS Independent",
],
keywords='python example package setuptools', # 关键词,方便搜索
# --- 6. 控制台脚本 (可选) ---
# 如果你希望你的包提供一个命令行工具,可以这样配置
# 安装后,用户可以在终端直接运行 'my-cli-tool' 命令
entry_points={
'console_scripts': [
'my-cli-tool=my_package.my_module:main_function',
],
},
)
entry_points 解释:
'my-cli-tool=my_package.my_module:main_function' 的意思是:
my-cli-tool: 用户在终端输入的命令名。my_package.my_module: 要执行的模块,即my_package/my_module.py。main_function: 该模块中要调用的函数。my_module.py中应该有一个名为main_function的函数。
构建你的包
在项目根目录(my_project/)下,打开终端,运行以下命令:
-
安装构建工具 现代推荐使用
build库来构建,它更规范。
(图片来源网络,侵删)pip install build
-
执行构建 运行
build命令,它会自动读取setup.py并生成两个文件:.tar.gz(源码分发包).whl(二进制 wheel 分发包)
python -m build
执行成功后,你的项目目录下会出现一个
dist/文件夹,里面就包含了这两个包文件。my_project/ ├── dist/ │ ├── my_awesome_package-0.1.0-py3-none-any.whl │ └── my_awesome_package-0.1.0.tar.gz ├── my_package/ ├── setup.py └── ...
本地安装和测试
在发布到 PyPI 之前,最好先在本地测试一下你的包是否可以正常安装和使用。
-
从
dist目录安装 使用pip的-e(editable) 选项进行开发模式安装,或者直接安装 wheel 文件。# 开发模式安装,修改源码后无需重新安装 pip install -e . # 或者安装构建好的 wheel 文件 pip install ./dist/my_awesome_package-0.1.0-py3-none-any.whl
-
测试安装 安装后,你可以在 Python 代码中导入你的包,或者在终端运行你的命令行工具(如果配置了
entry_points)。# 在 Python 解释器中测试 >>> import my_package >>> from my_package import my_module >>> my_module.some_function() "Hello from my_package!"
# 在终端测试命令行工具 $ my-cli-tool --help
上传到 PyPI
-
创建 PyPI 账号 如果你还没有,请访问 pypi.org 注册一个账号。
-
获取 API Token (推荐方式) 为了安全,不要使用你的用户名和密码,使用 API Token 是最佳实践。
- 登录 PyPI 账号,进入 "Account Settings" -> "API Tokens"。
- 点击 "Add API Token",给它一个名字(如
my_project_token),并勾选 "Add permissions for entire account"。 - 复制生成的 Token,它只会显示一次! 把它保存好。
-
安装
twinetwine是官方推荐的用于上传包到 PyPI 的工具。pip install twine
-
上传包 在你的项目根目录下,运行
twine命令,它会自动上传dist/目录下的所有文件。# 首次使用时,它会提示你输入你的 PyPI 用户名和密码。 # 但更推荐使用环境变量来设置 Token,更安全。 # 在终端运行: TWINE_USERNAME=__token__ TWINE_PASSWORD=your_api_token_here twine upload dist/* # 或者,你可以将 Token 配置在 ~/.pypirc 文件中,但 Token 方式更现代。 # 最简单的方式是直接交互式输入 # 对于 PyPI,用户名永远是 __token__ # 密码是你刚才复制的 API Token twine upload dist/* Username: __token__ Password: <paste_your_api_token_here>
上传成功后,稍等片刻,你就可以在 pypi.org 上搜索到你的包了!其他人现在也可以通过 pip install my-awesome-package 来安装你的项目了。
setup.cfg 和 pyproject.toml (现代方式)
虽然 setup.py 仍然广泛使用,但社区正在向更现代的配置方式迁移:
-
setup.cfg: 将setup.py中的大部分配置信息移到一个名为setup.cfg的 INI 风格的文件中。setup.py文件可以变得非常简单,甚至只是一个from setuptools import setup; setup()的调用。 -
pyproject.toml: 这是 PEP 518 引入的下一代标准,它使用 TOML 格式,是目前最推荐的方式,因为它能更好地构建系统(如pip和build)集成。
对于初学者来说,掌握 setup.py 已经足够应对绝大多数情况,但随着项目复杂度的增加,建议学习并迁移到 pyproject.toml。
| 步骤 | 命令/文件 | 描述 |
|---|---|---|
| 准备 | 创建项目结构 (my_package/, setup.py, README.md) |
组织你的代码和项目信息。 |
| 配置 | 编写 setup.py |
定义包的元数据和依赖。 |
| 构建 | pip install buildpython -m build |
生成 .whl 和 .tar.gz 分发包。 |
| 测试 | pip install -e . 或 pip install dist/*.whl |
在本地安装并测试你的包。 |
| 发布 | pip install twinetwine upload dist/* |
使用 twine 将包上传到 PyPI。 |
希望这份详细的指南能帮助你掌握 Python 项目的打包与分发!
