教學

如果你是 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 = 'bowsette@example.com'},
]

宣告專案元數據

我們的範例沒有使用 [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 套件安裝程式可以理解。有兩種構件:原始碼發佈包,通常稱為 sdists,以及 二進制發佈包,它使用名為 wheel 的自訂格式,因此它們通常稱為 wheels

sdists 和 wheels 的作用是什麼?

正如你可能從名稱中猜到的那樣,sdists 包含專案的原始碼,而 wheels 包含專案的已編譯[1] 版本,已準備好複製到檔案系統。

如果你的專案使用 Python 擴充模組,你的 wheels 將特定於平台和 Python 版本[2]

雖然發佈 wheels 並非強制性,但它們可以使使用者體驗更加良好。除非你有任何不發佈的理由,否則我們強烈建議你至少為最常見的系統發佈 wheels。當系統沒有可用的 wheels 時,仍然可以安裝專案,但需要從 sdist 建置,這涉及獲取所有建置依賴項並完成可能代價高昂的建置過程。

建置專案

在繼續之前,請確保你已將我們到目前為止建立的三個檔案提交到你的 Git 儲存庫 - meson-python 只會考慮 Git 知道的檔案。

要產生發佈構件,我們將使用 pypa/build 工具。它將建立一個臨時虛擬環境,安裝所有必要的建置依賴項,並要求 meson-python 建置構件。

$ pip install build
$ python -m build

如果建置成功,你將在 dist 資料夾中取得二進制構件。

為多個平台建置 wheels

如果我們的專案只包含純 Python (.py) 程式碼,我們剛建置的 wheel 將適用於所有平台,因為它是一個純 wheel,但如果專案包含原生程式碼,它將特定於我們機器的平台。

發佈時,你通常會想要至少為大多數其他更受歡迎的平台(Linux、Windows、macOS 等)建置。為了讓這項工作更容易,我們建議你查看 cibuildwheel 專案,它可以讓你自動化它。

建置隔離

預設情況下,使用 python -m build 或使用 pip 進行建置時會使用建置隔離。也就是說,建置前端在呼叫 meson-python 來建置 wheel 之前,會使用所有建置依賴項建立一個新的臨時虛擬環境。

如果你停用建置隔離,你必須負責確保 meson-python 和套件的所有其他建置依賴項已安裝在 Python 環境中。請注意,如果你使用虛擬環境進行建置,則必須啟用它(否則可能找不到 meson 或其他可執行檔)。

發佈專案

現在我們有了發佈構件,我們可以將它們上傳到儲存庫。我們將它們上傳到 Python 套件索引 (PyPI),這是大多數工具預設啟用的儲存庫。

為此,我們將使用 Twine

$ pip install twine
$ twine upload dist/*

上傳到 測試 PyPI

如果你不想上傳到真實索引,你可以改為上傳到 測試 PyPI

$ twine upload -r testpypi dist/*

你可以在 其 PyPA 文件頁面中找到有關如何使用 測試 PyPI 的更多資訊。

之後,您的套件應該會在 PyPI 上可供使用,並可使用 pip 安裝。

$ pip install our-first-project