教程

如果您不熟悉 Python 打包,请不要担心!

我们将快速介绍发布 Python 包的步骤,并逐步指导您开始操作。

创建 Meson 项目

首先,我们需要一个要发布的项目。由于 meson-python 是基于 Meson 构建的,我们将创建一个非常简单的 Meson 项目。您可能已经有一个想要发布的 Meson 项目,在这种情况下,您可以跳过此步骤。

模块

首先,我们创建一个简单的 Python 模块。我们将使用一个本机模块,因为这正是 meson-python 在其他 Python 构建后端中脱颖而出的地方。

our_first_module.c
#include <Python.h>

static PyObject* foo(PyObject* self)
{
    return PyUnicode_FromString("bar");
}

static PyMethodDef methods[] = {
    {"foo", (PyCFunction)foo, METH_NOARGS, NULL},
    {NULL, NULL, 0, NULL},
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT,
    "our_first_module",
    NULL,
    -1,
    methods,
};

PyMODINIT_FUNC PyInit_our_first_module(void)
{
    return PyModule_Create(&module);
}

在这里,我们创建了一个名为 our_first_module 的小型模块,它有一个名为 foo 的函数,该函数只是返回 "bar"

使用 C API

如果您需要帮助编写使用 Python C API 的本机模块,我们建议您查看以下资源。

Meson 构建描述

现在,我们需要创建 Meson 构建描述文件。它告诉 Meson 我们想要构建什么,以及如何构建。

meson.build
project('purelib-and-platlib', 'c')

py = import('python').find_installation(pure: false)

py.extension_module(
    'our_first_module',
    'our_first_module.c',
    install: true,
)

在这里,我们使用 Meson 的 Python 模块 来构建我们的 our_first_module 模块。我们确保安装它,通过将 install: true 传递给 extension_module,因为 meson-python 只会在二进制发行版中包含 Meson 要安装到系统上的目标。拥有未安装的目标允许您构建供构建内使用或用于测试的目标。

配置我们的 Python 包

现在,我们需要告诉 Python 打包工具使用哪个构建后端来构建我们的包。我们通过在 pyproject.toml 文件中创建一个 build-system 部分来做到这一点,该文件用于配置 Python 打包工具。

build-system 部分中,我们需要定义两个键,build-backendrequiresbuild-backend 定义了应为项目使用哪个构建后端 - 将其设置为 'mesonpy' 以使用 meson-pythonrequires 允许我们指定构建过程需要安装哪些软件包,它应包括 meson-python 以及您可能需要的任何其他依赖项(例如,Cython)。

pyproject.toml
[build-system]
build-backend = 'mesonpy'
requires = ['meson-python']

指定要使用哪个后端后,我们将要定义包元数据。这在 project 部分中完成,格式相当不言自明

pyproject.toml
...

[project]
name = 'our-first-project'
version = '0.0.1'
description = 'Our first Python project, using meson-python!'
readme = 'README.md'
requires-python = '>=3.8'
license = {file = 'LICENSE.txt'}
authors = [
  {name = 'Bowsette Koopa', email = '[email protected]'},
]

声明项目元数据

我们的示例没有使用 [project] 部分中提供的所有字段。查看 PyPA 关于项目元数据的文档,以获取更多示例和详细信息。

测试项目

现在我们应该有一个有效的 Python 项目,所以让我们测试一下。

我们将使用 pip 安装它

$ pip install .
$ pip list
...
our-first-project   0.0.1
...

之后,我们应该能够导入并尝试我们的模块。

$ python
>>> import our_first_module
>>> our_first_module.foo()
'bar'

创建您的第一个发行版

现在我们有了一个有效的 Python 项目,我们可以发布它。

要发布项目,我们首先需要生成发行版工件,这些文件是 Python 包安装程序理解的标准化格式。有两种类型的工件,源代码发行版,通常称为sdist,和 二进制发行版,它使用名为wheel 的自定义格式,因此它们通常被称为wheel

sdist 和 wheel 的作用是什么?

正如您从名称中可能猜到的那样,sdist 包含项目的源代码,而 wheel 包含项目的已编译 [1] 版本,准备复制到文件系统。

如果您的项目使用 Python 扩展模块,您的 wheel 将特定于平台和 Python 版本 [2]

虽然分发 wheel 不是强制性的,但它们使用户体验更加友好。除非您有充分的理由,否则我们强烈建议您至少为最常见的系统分发 wheel。当系统上没有 wheel 可用时,项目仍然可以安装,但需要从 sdist 构建,这涉及获取所有构建依赖项并经过可能昂贵的构建过程。

构建项目

在继续之前,请确保您已将我们迄今为止创建的三个文件提交到您的 Git 存储库 - meson-python 只会考虑 Git 知道的那些文件。

要生成发行版工件,我们将使用 pypa/build 工具。它将创建一个临时虚拟环境,安装所有必需的构建依赖项,并要求 meson-python 构建工件。

$ pip install build
$ python -m build

如果构建成功,您将在 dist 文件夹中获得二进制工件。

为多个平台构建 wheel

如果我们的项目只包含纯 Python (.py) 代码,我们刚刚构建的 wheel 将在所有平台上都能正常工作,因为它是一个纯 wheel,但是如果项目包含本机代码,它将特定于我们机器的平台。

在发布时,您通常希望至少为大多数其他流行平台(Linux、Windows、macOS 等)构建。为了使这项工作更容易,我们建议您查看 cibuildwheel 项目,它允许您自动执行此操作。

构建隔离

使用 python -m buildpip 构建默认情况下使用构建隔离。也就是说,构建前端创建一个新的、临时的虚拟环境,其中包含所有构建依赖项,然后调用 meson-python 来构建 wheel。

如果您禁用构建隔离,您有责任确保 meson-python 以及软件包的所有其他构建依赖项已安装在 Python 环境中。请注意,如果您使用虚拟环境进行构建,则必须激活它(否则,可能找不到 meson 或其他可执行文件)。

分发项目

现在我们有了发行版工件,我们可以将它们上传到存储库。我们将把它们上传到 Python 包索引 (PyPI),它是大多数工具默认情况下启用的存储库。

为此,我们将使用 Twine

$ pip install twine
$ twine upload dist/*

上传到 Test PyPI

如果您不想上传到真实索引,您可以改为上传到 Test PyPI

$ twine upload -r testpypi dist/*

您可以在 Test PyPIPyPA 文档页面 中找到有关如何使用 Test PyPI 的更多信息。

之后,您的软件包应该可以在 PyPI 上使用,并可以使用 pip 安装。

$ pip install our-first-project