跳到主要内容

Python 包分发

在Python编程旅程中,你可能已经开发了一些有用的功能或工具,希望与他人分享。Python包分发是将你的代码组织成可分享、可安装的格式的过程,让其他人能够方便地使用你的代码。本文将介绍如何准备、打包和分发你的Python代码。

为什么需要包分发?

想象一下以下场景:

  • 你开发了一个实用的数据分析库,想让团队成员轻松安装使用
  • 你创建了一个解决特定问题的工具,希望与整个Python社区分享
  • 你需要在多个项目中重复使用相同的代码,而不是复制粘贴

包分发解决了这些问题,它让你的代码变得:

  1. 可安装 - 通过简单的pip install命令安装
  2. 可管理 - 包含版本控制和依赖管理
  3. 可发现 - 可以发布到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是一个现代的项目配置文件,它定义了构建系统需求:

toml
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"

setup.cfg

setup.cfg包含了包的元数据和配置:

ini
[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.cfgpyproject.toml的组合。

构建包

一旦你完成了包的结构和配置,你可以构建分发包。首先确保你安装了最新的构建工具:

bash
pip install --upgrade build

然后在项目根目录下构建包:

bash
python -m build

成功执行后,将在dist/目录下生成两种格式的分发包:

  • 源码分发(Source Distribution,.tar.gz文件)
  • 轮子分发(Wheel Distribution,.whl文件)

本地安装测试

在发布之前,最好先在本地测试安装你的包:

bash
pip install dist/mypackage-0.1.0-py3-none-any.whl

或者直接从源码安装(开发模式):

bash
pip install -e .

然后打开Python解释器测试导入:

python
import mypackage
# 测试包的功能

发布到PyPI

要将包发布到PyPI,首先需要注册一个PyPI账户,并安装twine工具:

bash
pip install --upgrade twine

上传到TestPyPI(推荐先测试)

TestPyPI是一个测试环境,可以先在这里测试发布流程:

bash
twine upload --repository-url https://test.pypi.org/legacy/ dist/*

然后可以从TestPyPI安装测试:

bash
pip install --index-url https://test.pypi.org/simple/ mypackage

上传到正式PyPI

确认一切正常后,上传到正式的PyPI:

bash
twine upload dist/*

成功后,其他人就可以通过pip install mypackage安装你的包了!

实际案例:创建一个简单的数学工具包

让我们通过一个实际例子了解整个流程:假设我们创建一个名为mathhelper的简单数学工具包。

  1. 创建项目结构:
mathhelper/
├── LICENSE
├── README.md
├── pyproject.toml
├── setup.cfg
├── src/
│ └── mathhelper/
│ ├── __init__.py
│ └── stats.py
└── tests/
└── test_stats.py
  1. 编写简单的功能(src/mathhelper/stats.py):
python
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]
  1. __init__.py中导入这些函数,使它们可以直接从包中导入:
python
from .stats import mean, median

__version__ = '0.1.0'
  1. 配置setup.cfg
ini
[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
  1. 配置pyproject.toml
toml
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
  1. 构建和安装:
bash
python -m build
pip install dist/mathhelper-0.1.0-py3-none-any.whl
  1. 测试使用:
python
>>> from mathhelper import mean, median
>>> mean([1, 2, 3, 4, 5])
3.0
>>> median([1, 2, 3, 4, 5])
3

版本控制和更新

当你需要更新包时,遵循以下步骤:

  1. 更新代码和功能
  2. setup.cfg中增加版本号(例如从0.1.0变为0.1.1)
  3. 重新构建并上传新版本
  4. 用户可以通过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中指定:

ini
[options]
install_requires =
requests>=2.20.0
numpy>=1.15.0

命令行脚本

可以为包添加可执行的命令行脚本:

ini
[options.entry_points]
console_scripts =
mathcli = mathhelper.cli:main

额外依赖

定义可选的依赖组:

ini
[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包,与他人分享你的代码和创意!

练习

  1. 创建一个简单的Python包,包含2-3个你经常使用的辅助函数
  2. 配置好所有必要的文件和元数据
  3. 在本地构建并安装测试
  4. 尝试发布到TestPyPI(可选)

额外资源

警告

记住保护你的PyPI账户凭据,最好使用API令牌而不是密码进行上传。如果你的包变得流行,确保妥善管理它的安全性和维护。