Python 包分发
在Python编程旅程中,你可能已经开发了一些有用的功能或工具,希望与他人分享。Python包分发是将你的代码组织成可分享、可安装的格式的过程,让其他人能够方便地使用你的代码。本文将介绍如何准备、打包和分发你的Python代码。
为什么需要包分发?
想象一下以下场景:
- 你开发了一个实用的数据分析库,想让团队成员轻松安装使用
- 你创建了一个解决特定问题的工具,希望与整个Python社区分享
- 你需要在多个项目中重复使用相同的代码,而不是复制粘贴
包分发解决了这些问题,它让你的代码变得:
- 可安装 - 通过简单的
pip install
命令安装 - 可管理 - 包含版本控制和依赖管理
- 可发现 - 可以发布到PyPI(Python包索引)上供所有人使用
包分发的基本概念
在开始之前,让我们了解一些基本术语:
- 包(Package):包含
__init__.py
文件的目录,可以包含多个模块 - 发行版(Distribution):可共享的Python代码包,包含了包/模块和元数据
- wheel:一种预构建的包格式,安装更快、更容易
- sdist:源代码分发,包含源代码和构建指令
- PyPI:Python Package Index,官方的第三方Python包仓库
- setuptools:最常用的Python包构建工具
- pip:Python的包安装工具
准备包分发:项目结构
一个可分发的Python包通常有以下结构:
mypackage/
├── LICENSE
├── README.md
├── pyproject.toml
├── setup.cfg
├── src/
│ └── mypackage/
│ ├── __init__.py
│ ├── module1.py
│ └── module2.py
└── tests/
├── test_module1.py
└── test_module2.py
使用src/
目录结构是现代Python包的最佳实践,它可以避免开发时的导入问题。
创建配置文件
pyproject.toml
pyproject.toml
是一个现代的项目配置文件,它定义了构建系统需求:
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
setup.cfg
setup.cfg
包含了包的元数据和配置:
[metadata]
name = mypackage
version = 0.1.0
author = Your Name
author_email = your.email@example.com
description = A small example package
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/yourusername/mypackage
project_urls =
Bug Tracker = https://github.com/yourusername/mypackage/issues
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License
Operating System :: OS Independent
[options]
package_dir =
= src
packages = find:
python_requires = >=3.6
[options.packages.find]
where = src
你也可以使用setup.py
文件来配置包,但现代Python推荐使用setup.cfg
和pyproject.toml
的组合。
构建包
一旦你完成了包的结构和配置,你可以构建分发包。首先确保你安装了最新的构建工具:
pip install --upgrade build
然后在项目根目录下构建包:
python -m build
成功执行后,将在dist/
目录下生成两种格式的分发包:
- 源码分发(Source Distribution,.tar.gz文件)
- 轮子分发(Wheel Distribution,.whl文件)
本地安装测试
在发布之前,最好先在本地测试安装你的包:
pip install dist/mypackage-0.1.0-py3-none-any.whl
或者直接从源码安装(开发模式):
pip install -e .
然后打开Python解释器测试导入:
import mypackage
# 测试包的功能
发布到PyPI
要将包发布到PyPI,首先需要注册一个PyPI账户,并安装twine
工具:
pip install --upgrade twine
上传到TestPyPI(推荐先测试)
TestPyPI是一个测试环境,可以先在这里测试发布流程:
twine upload --repository-url https://test.pypi.org/legacy/ dist/*
然后可以从TestPyPI安装测试:
pip install --index-url https://test.pypi.org/simple/ mypackage
上传到正式PyPI
确认一切正常后,上传到正式的PyPI:
twine upload dist/*
成功后,其他人就可以通过pip install mypackage
安装你的包了!
实际案例:创建一个简单的数学工具包
让我们通过一个实际例子了解整个流程:假设我们创建一个名为mathhelper
的简单数学工具包。
- 创建项目结构:
mathhelper/
├── LICENSE
├── README.md
├── pyproject.toml
├── setup.cfg
├── src/
│ └── mathhelper/
│ ├── __init__.py
│ └── stats.py
└── tests/
└── test_stats.py
- 编写简单的功能(
src/mathhelper/stats.py
):
def mean(numbers):
"""Calculate the arithmetic mean of a list of numbers."""
if not numbers:
return 0
return sum(numbers) / len(numbers)
def median(numbers):
"""Find the median value in a list of numbers."""
if not numbers:
return 0
sorted_numbers = sorted(numbers)
n = len(sorted_numbers)
if n % 2 == 0:
return (sorted_numbers[n//2 - 1] + sorted_numbers[n//2]) / 2
else:
return sorted_numbers[n//2]
- 在
__init__.py
中导入这些函数,使它们可以直接从包中导入:
from .stats import mean, median
__version__ = '0.1.0'
- 配置
setup.cfg
:
[metadata]
name = mathhelper
version = 0.1.0
author = Your Name
author_email = your.email@example.com
description = A simple math helper library
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/yourusername/mathhelper
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License
Operating System :: OS Independent
[options]
package_dir =
= src
packages = find:
python_requires = >=3.6
[options.packages.find]
where = src
- 配置
pyproject.toml
:
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
- 构建和安装:
python -m build
pip install dist/mathhelper-0.1.0-py3-none-any.whl
- 测试使用:
>>> from mathhelper import mean, median
>>> mean([1, 2, 3, 4, 5])
3.0
>>> median([1, 2, 3, 4, 5])
3
版本控制和更新
当你需要更新包时,遵循以下步骤:
- 更新代码和功能
- 在
setup.cfg
中增加版本号(例如从0.1.0变为0.1.1) - 重新构建并上传新版本
- 用户可以通过
pip install --upgrade mathhelper
更新到最新版本
遵循语义化版本规范可以清晰地传达每次更新的重要性:
- 修复bug:增加修订号(1.0.0 -> 1.0.1)
- 添加向后兼容的功能:增加次版本号(1.0.0 -> 1.1.0)
- 进行不兼容的更改:增加主版本号(1.0.0 -> 2.0.0)
高级功能
虽然基本分发很简单,但还有一些高级功能可以增强你的包:
依赖管理
如果你的包依赖其他库,可以在setup.cfg
中指定:
[options]
install_requires =
requests>=2.20.0
numpy>=1.15.0
命令行脚本
可以为包添加可执行的命令行脚本:
[options.entry_points]
console_scripts =
mathcli = mathhelper.cli:main
额外依赖
定义可选的依赖组:
[options.extras_require]
dev =
pytest>=6.0
black>=21.0
doc =
sphinx>=3.0
sphinx-rtd-theme>=0.5
用户可以通过pip install mathhelper[dev]
安装带开发工具的版本。
总结
Python包分发是将你的代码分享给世界的重要步骤。通过本文,你学习了:
- 如何组织包结构
- 如何配置包元数据
- 构建和测试包的方法
- 发布包到PyPI的步骤
- 版本控制和更新包的最佳实践
掌握这些技能后,你就可以创建专业的Python包,与他人分享你的代码和创意!
练习
- 创建一个简单的Python包,包含2-3个你经常使用的辅助函数
- 配置好所有必要的文件和元数据
- 在本地构建并安装测试
- 尝试发布到TestPyPI(可选)
额外资源
- Python Packaging User Guide - 官方的Python包装指南
- Packaging Python Projects - 详细的教程
- setuptools 文档 - 最常用的Python包装工具文档
- PyPI - Python包索引
- TestPyPI - 用于测试的Python包索引
记住保护你的PyPI账户凭据,最好使用API令牌而不是密码进行上传。如果你的包变得流行,确保妥善管理它的安全性和维护。