Jump to content

Python package guidelines (Русский)

From ArchWiki
Состояние перевода: На этой странице представлен перевод статьи Python package guidelines. Дата последней синхронизации: 17 марта 2026. Вы можете помочь синхронизировать перевод, если в английской версии произошли изменения.
Указания по созданию пакетов

32-bitCLRCMakeCrossDKMSEclipseElectronFontFree PascalGNOMEGoHaskellJavaKDEKernelLispMesonMinGWNode.jsNonfreeOCamlPerlPHPPythonRRubyRustShellVCSWebWine

Этот документ охватывает стандарты и рекомендации по написанию файлов PKGBUILD для программ, работающих на Python.

Именование пакета

Для библиотек Python 3 используйте python-имямодуля. Также используйте префикс, если пакет предоставляет программу, тесно связанную с экосистемой Python (например, pip или tox). Для других приложений используйте только имя программы.

Примечание Название пакета должно быть полностью в нижнем регистре.

Архитектура

Смотрите PKGBUILD (Русский)#arch.

Пакет Python, содержащий расширения C, является архитектурно-зависимым. В противном случае он, скорее всего, является архитектурно-независимым.

Пакеты, собираемые с помощью setuptools, определяют свои расширения C с помощью ключевого слова ext_modules в setup.py.

Исходники

Примечание Согласно RFC0020, исходники стоит по возможности получать непосредственно у апстрима, а не из sdist-архивов на PyPI.

URL загрузки, связанные с сайтом PyPI, содержат непредсказуемый хэш, который необходимо получать с сайта PyPI каждый раз, когда пакет должен быть обновлён. Это делает их непригодными для использования в PKGBUILD. PyPI предоставляет альтернативную стабильную схему: массив source должен использовать следующие шаблоны URL:

Архив с исходным кодом
https://files.pythonhosted.org/packages/source/${_name::1}/${_name//-/_}/${_name//-/_}-$pkgver.tar.gz
Пакет wheel, содержащий только Python-код
https://files.pythonhosted.org/packages/py2.py3/${_name::1}/$_name/${_name//-/_}-$pkgver-py2.py3-none-any.whl (для пакета, совместимого с Python 2 и Python 3)
https://files.pythonhosted.org/packages/py3/${_name::1}/$_name/${_name//-/_}-$pkgver-py3-none-any.whl (для пакета, совместимого только с Python 3)
Обратите внимание, что имя дистрибутива может содержать тире, а его представление в имени файла wheel — нет (они преобразуются в символы подчёркивания).
Архитектурно-зависимый пакет wheel
Дополнительные массивы, специфичные для архитектуры, могут быть добавлены путём добавления подчёркивания и имени архитектуры, например, source_x86_64=('...'). Также можно использовать _py=cp310, чтобы не повторять версию Python:
https://files.pythonhosted.org/packages/$_py/${_name::1}/$_name/${_name//-/_}-$pkgver-$_py-${_py}m-manylinux1_x86_64.whl

Обратите внимание, что используется переменная _name вместо pkgname, поскольку пакеты Python обычно имеют префикс python-. Эта переменная может быть определена следующим образом:

_name=${pkgname#python-}

Методы установки

Пакеты Python обычно устанавливаются с помощью специального менеджера пакетов, такого как pip, который получает пакеты из онлайн-репозитория (обычно PyPI, Python Package Index) и отслеживает соответствующие файлы.

Однако для управления пакетами Python из PKGBUILD необходимо «установить» пакет Python во временное место $pkgdir/usr/lib/python<версия Python>/site-packages/$pkgname.

Для пакетов Python, использующих стандартные метаданные для указания бэкенда сборки в файле pyproject.toml, это проще всего сделать с помощью python-build и python-installer. Старые пакеты могут не указывать, что они используют setuptools, и предлагать только setup.py, который должен быть вызван вручную.

Примечание Зависимости, прописанные в метаданных, должны быть добавлены в массив depends, иначе они не будут установлены.

По стандартам (PEP 517)

Совет Если сборка производится из исходников апстрима, а апстрим полагается на git для получения строки версии проекта, перед сборкой wheel-пакета необходимо задать значение $pkgver переменным окружения, специфичным для используемого инструментария:

Рабочий процесс, основанный на стандартах, прост: создайте wheel-пакет с помощью python-build и установите его в $pkgdir с помощью python-installer:

Примечание Помимо пакетов python-build и python-installer, в makedepends также необходимо добавить бэкенд сборки. Все доступные в репозиториях Archlinux бэкенды добавлены в группу python-build-backend. Чтобы узнать, какой бэкенд необходим для сборки проекта, смотрите строку build-system.build-backend в его файле pyproject.toml. Если бэкенд не указан, по умолчанию будет использоваться python-setuptools.
makedepends=(python-build python-installer python-wheel)

build() {
    cd $_name-$pkgver
    python -m build --wheel --no-isolation
}

package() {
    cd $_name-$pkgver
    python -m installer --destdir="$pkgdir" dist/*.whl
}

где:

  • --wheel указывает создать только wheel-пакет, без архива с исходным кодом.
  • --no-isolation указывает, что пакет должен быть собран с использованием установленных в системе зависимостей (включая пакеты, указанные вами в depends); по умолчанию без этой опции для сборки создаётся изолированное виртуальное окружение.
  • --destdir="$pkgdir" предотвращает попытку прямой установки в хост-систему, а не внутрь файла пакета, что привело бы к ошибке доступа
  • --compile-bytecode=... или --no-compile-bytecode можно передать в installer, но значение по умолчанию выбрано разумно, поэтому в этом нет необходимости.
Примечание Пропуск build и помещение файла .whl в массив source не рекомендуется и должно использоваться только в тех случаях, когда сборка из исходников невозможна (например, для программ, которые поставляются только в виде wheel-пакетов и потому не могут быть собраны из исходных текстов).
Совет Если ваш пакет является VCS-пакетом (python-…-git), добавьте в функцию prepare команду git -C "${srcdir}/${pkgname}" clean -dfx. Это удалит устаревшие wheel-пакеты вместе с другими артефактами сборки и поможет избежать проблем в дальнейшем. Смотрите также issues в setuptools и Poetry.

setuptools или distutils

Если pyproject.toml отсутствует или не содержит таблицу [build-system], это означает, что проект использует старый формат с файлом setup.py, который вызывает функцию setup из setuptools или distutils.core. Обычно такие пакеты можно собрать и установить тем же способом, при помощи python-build и python-installer, и это предпочтительный метод, но для таких проектов понадобится добавить в makedepends пакет python-setuptools.

Вы по-прежнему можете собрать и установить такие пакеты, напрямую используя setup.py. Этот способ описан ниже для тех случаев, когда современный PEP 517 не работает или не может быть использован. Тем не менее, помните, что это устаревший подход и использовать его не рекомендуется. Сборочная система сообщит Вам об этом таким предупреждением на этапе package:

SetuptoolsDeprecationWarning: setup.py install is deprecated.

Также имейте в виду, что, начиная с версии 3.12, библиотека distutils не включена в стандартную поставку Python, что означает, что пакеты, собираемые старым способом через setup.py, как правило должны включать пакет python-setuptools в makedepends, поскольку он предоставляет свою собственную версию distutils.

makedepends=('python-setuptools')

build() {
    cd $_name-$pkgver
    python setup.py build
}

package() {
    cd $_name-$pkgver
    python setup.py install --root="$pkgdir" --optimize=1
}

где:

  • --root="$pkgdir" работает как --destdir выше
  • --optimize=1 заранее компилирует оптимизированные файлы байткода (.opt-1.pyc), чтобы их мог отслеживать pacman, вместо ленивого их создания при запуске программы.
  • Добавление --skip-build оптимизирует ненужную попытку повторного выполнения шагов сборки, уже запущенных в функции build(), если это имеет место.

Если для сборки используется python-setuptools-scm, скорее всего, Вы получите ошибку:

LookupError: setuptools-scm was unable to detect version for /build/python-jsonschema/src/jsonschema-3.2.0.

Make sure you're either building from a fully intact git repository or PyPI tarballs. Most other sources (such as GitHub's tarballs, a git checkout without the .git folder) don't contain the necessary metadata and will not work.

Чтобы пакет собрался, нужно экспортировать переменную окружения SETUPTOOLS_SCM_PRETEND_VERSION со значением $pkgver:

export SETUPTOOLS_SCM_PRETEND_VERSION=$pkgver

Проверка

Примечание
  • Избегайте использования tox для запуска тестов, поскольку он предназначен для проверки воспроизводимых конфигураций, загруженных из PyPI во время работы tox, и не проверяет версию, которая будет установлена пакетом. Это противоречит целям самой функции check;
  • Не используйте в checkdepends плагины pytest для линтинга, coverage-тестов и проверки типов (см. раздел #Отключение опций pytest). Они лишь усложняют процесс, но не требуются для сборки пакетов, поскольку не проверяют корректность работы программ (они используются для других проверок и в основном нужны самим разработчикам проекта);
  • Избегайте использования относительных путей при установке пользовательского PYTHONPATH для тестов, так как это может привести к неочевидным ошибкам. Старайтесь всегда использовать абсолютные пути.

Большинство проектов Python предоставляют набор тестов в файле или каталоге с названием test или tests и используют для их запуска unittest runner из пакета python, nosetests из пакета python-nose или pytest из пакета python-pytest. В общем случае для запуска набора тестов достаточно просто запустить nosetests или pytest.

check(){
    cd $srcdir/foo-$pkgver

    # встроенный unittest
    python -m unittest discover -v

    # nosetests
    nosetests

    # pytest
    pytest
}

Если есть скомпилированное расширение C, тесты необходимо запускать, используя $PYTHONPATH, отражающий текущую мажорную и минорную версию Python, чтобы найти и загрузить его.

check(){
    cd $_name-$pkgver
    local python_version=$(python -c 'import sys; print("".join(map(str, sys.version_info[:2])))')

    # встроенный unittest
    PYTHONPATH="$PWD/build/lib.linux-$CARCH-cpython-$python_version" python -m unittest discover -vs .

    # nosetests
    PYTHONPATH="$PWD/build/lib.linux-$CARCH-cpython-$python_version" nosetests

    # pytest
    PYTHONPATH="$PWD/build/lib.linux-$CARCH-cpython-$python_version" pytest
}

Советы и рекомендации

Указание версии Python

Иногда во время подготовки, сборки, тестирования или установки требуется указать мажорную и минорную версию Python для системы. Не записывайте это жёстко в коде (например, 3.9 или 3.10), а запустите интерпретатор Python для получения информации и сохранения её в локальной переменной:

check(){
  local python_version=$(python -c 'import sys; print(".".join(map(str, sys.version_info[:2])))')
  ...
}

Использование site-packages

Иногда во время сборки, тестирования или установки требуется обратиться к системному каталогу site-packages. Не следует записывать путь жёстко в коде, вместо этого запустите интерпретатор Python для получения пути и сохранения его в локальной переменной:

check(){
  local site_packages=$(python -c "import site; print(site.getsitepackages()[0])")
  ...
}

Тестовый каталог в site-packages

Проверяйте, что Вы не установили каталог с именем tests прямо в site-packages (т. е. /usr/lib/pythonX.Y/site-packages/tests/). Это может приводить к конфликтам между пакетами. Некоторые Python-проекты, использующие setuptools, иногда неправильно настроены и добавляют каталог с тестами в качестве Python-пакета верхнего уровня. Если вы столкнулись с этим, то можете помочь, отправив проекту сообщение об ошибке с просьбой исправить это, например, вот так.

Отключение опций pytest

При запуске pytest старайтесь не использовать дополнительные плагины, особенно плагины для линтинга и coverage-тестов: они не нужны для проверки функциональности программы, но изменения в них легко могут привести к сбоям процесса сборки. Для отключения опций pytest (например, addopts), предпочтительнее использовать переопределение параметров через команды файла PKGBUILD, а не вносить изменения патчами, поскольку при обновлении пакетов эти патчи будет сложнее поддерживать.

Чтобы отключить все дополнительные параметры, используйте:

pytest -o addopts=""

Исправление проблемы воспроизводимости с meson-python

meson-python в качестве бэкенда сборки PEP 517 использует случайные пути к папкам, что приводит к проблемам воспроизводимости. Этого можно избежать, жёстко задав каталог с помощью флага -Cbuild-dir:

python -m build --wheel --no-isolation -Cbuild-dir=build

Запуск тестов после установки пакета

Некоторые пакеты необходимо установить для того, чтобы тесты прошли успешно. В таких случаях (например, в пакете python-narwhals) вы можете создать виртуальное окружение, в котором этот пакет будет установлен и протестирован:

python -m venv --system-site-packages test-env
test-env/bin/python -m installer dist/*.whl
test-env/bin/python -P -m pytest