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

Jump to content

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

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

Этот документ охватывает стандарты и рекомендации по написанию файлов 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` переменным окружения, специфичным для используемого инструментария:

- python-flit-core, python-hatch-vcs и python-setuptools-scm: `SETUPTOOLS_SCM_PRETEND_VERSION`
- python-pbr: `PBR_VERSION`
- python-pdm-backend: `PDM_BUILD_SCM_VERSION`

Рабочий процесс, основанный на стандартах, прост: создайте 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

Category:

- Arch package guidelines (Русский)

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