发布开源的Python包到PyPI
在使用Python语言编写程序或者开发软件时候,不可避免地会使用到标准库之外的第三方软件包。PyPI(Python Package Index,Python软件包索引)就是官方的Python软件包服务,开发者使用pip install
命令时,默认会检索这个服务,并下载安装所需的软件包到本地项目中。除了自由地使用这些软件包之外,开发者也许会开源和发布自己的代码。本文介绍如何发布软件包到PyPI中。
软件包的组织结构 🔗
Python 官方并没有对软件包结构的强制要求,不同的项目可以采用适合自己的风格。鉴于 Python 悠久的历史,不同的项目可能会有不同的风格。但是,一个广泛认同和易于理解的组织结构,能够让维护者和使用者更好地使用它。为此,可以参考现有流行的 Python 包,或者搜索一下业界的实践。
假设软件包的名字是foobar
,那么它的结构可以如下所示。
foobar/
src/
foobar/
__init__.py
cli.py # 命令行脚本(可选)
tests/
setup.py
README.md
requirements.txt # 开发软件包时所需的第三方包清单
LICENSE
定义构建软件包的元信息 🔗
在编写好了软件包的功能代码后,就需要编写软件包的元信息,以便进行打包。
import pathlib
from setuptools import setup, find_packages
here = pathlib.Path(__file__).parent.resolve()
long_description = (here / "README.md").read_text(encoding="utf-8")
setup(
name="foobar", # 软件包的名字
version="0.0.1", # 软件包的版本,每次发布时,都需要升级该版本号
long_description=long_description,
long_description_content_type="text/markdown",
classifiers=[
"Programming Language :: Python :: 3"
],
package_dir={"": "src"},
packages=find_packages(where="src"),
python_requires=">=3.7, <4",
install_requires=[ # 本软件包所依赖的第三方包。在安装本软件包时,会自动安装它们
"click"
],
entry_points={
"console_scripts": [ # 软件包的命令行程序(可选)。在安装软件包时,会安装它们
"foobar=foobar.cli:main" # 指向了软件包代码中的某个模块的函数
]
}
)
本地验证和测试 🔗
在正式发布之前,先在本地验证。反复安装、测试和卸载软件包,直到测试成功:
pip install -e foobar/ # 安装
pip uninstall -e foobar # 卸载
如果软件包里提供了命令行程序,那么记得测试命令行程序。
发布软件包到PyPI 🔗
首先创建一个PyPI
的账号。
发布软件包有两种方式:
- 第一种是传统方式,即在PyPI的Account Settings里创建API Token,然后使用API Token进行认证并发布。
- 第二种是使用PyPI的发布(Publishing)特性,通过可信发布者(Trusted Publisher)进行发布。操作方法是在PyPI里创建一个Github类型的Publisher,关联对应的代码仓库。然后就可以在对应项目的Github Actions上自动地进行鉴权和发布了。
使用控制代码系统管理代码,并使用自动化的CI/CD流水线进行构建和发布,这是发布可靠软件的默认实践了。而Github和Githb Actions正是可以拿来即用的工具,因此第二种方式是推荐的方式。
使用API Token发布软件包到PyPI 🔗
见官方文档 Uploading the distribution archives。
从Github Actions发布软件包到PyPI 🔗
首先得使用Github管理代码。因此需要在Github上创建代码仓库,然后将代码推送到仓库中。
接着在PyPI的Publishing页面里添加创建publisher
(即Add a new pending publisher
)。需要填写PyPI项目名称(PyPI Project Name
)、所有者(Owner
,即Github的用户名或者组织名)、代码库名称(Repository name
)、Github Actions Workflow的文件名(Workflow name
)等。
然后在Github Actions里的Workflow中设定权限,并使用gh-action-pypi-publish进行发布。
下面是一个使用两步发布(先构建和打包,再发布)的示例配置,它会在创建了以v
开头的标签后,进行构建和发布:
name: release
on:
push:
tags:
- 'v*'
jobs:
build:
name: Build distribution 📦
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.x"
- name: Install pypa/build
run: >-
python3 -m
pip install
build
--user
- name: Build a binary wheel and a source tarball
run: python3 -m build
- name: Store the distribution packages
uses: actions/upload-artifact@v3
with:
name: python-package-distributions
path: dist/
publish:
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/foobar # 此处为PyPI上的软件包地址
permissions:
id-token: write # 必须设置这里的权限
needs:
- build
steps:
- name: Download all the dists
uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/
- name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
测试 🔗
发布之后,在 PyPI 网站查看新发布的软件包,并使用 pip install
下载和安装,然后确保功能测试通过。