# Создание и тестирование Python

Узнайте, как создать рабочий процесс непрерывной интеграции (CI) для создания и тестирования вашего проекта на Python.

> \[!NOTE]
> GitHub Enterprise Serverразмещенные в данный момент средства выполнения не поддерживаются в GitHub.

## Введение

В этом руководстве показано, как создать, протестировать и опубликовать пакет на Python.

Раннеры, размещённые на GitHub, имеют кэш инструментов с предустановленным программным обеспечением, включающим Python и PyPy. Вам ничего устанавливать не нужно. Полный список программного обеспечения up-to-date и предустановленные версии Python и PyPy см. [Средства выполнения тестов, размещенные в GitHub](/ru/enterprise-server@3.22/actions/concepts/runners/github-hosted-runners#preinstalled-software-for-github-owned-images).

## Необходимые компоненты

Вы должны быть знакомы с YAML и синтаксисом для GitHub Actions. Дополнительные сведения см. в разделе [Написание рабочих процессов](/ru/enterprise-server@3.22/actions/how-tos/write-workflows).

Рекомендуем иметь базовое понимание Python и pip. Дополнительные сведения см. в разделе:

* [Начинаю с Python](https://www.python.org/about/gettingstarted/)
* [Диспетчер пакетов pip](https://pypi.org/project/pip/)

### Использование локальных средств выполнения GitHub Enterprise Server

При использовании действий установки (например `actions/setup-LANGUAGE`) GitHub Enterprise Server с локальными средствами выполнения, возможно, потребуется настроить кэш средств на запусках, у которых нет доступа к Интернету. Дополнительные сведения см. в разделе [Настройка кэша инструментов для локально размещенных средств выполнения без доступа к Интернету](/ru/enterprise-server@3.22/admin/managing-github-actions-for-your-enterprise/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access).

## Использование шаблона рабочего процесса на Python

Чтобы быстро приступить к работе, добавьте шаблон рабочего процесса в `.github/workflows` каталог репозитория.

GitHub предоставляет шаблон рабочего процесса для Python, который должен работать, если в вашем репозитории уже есть хотя бы один файл `.py`. В последующих разделах этого руководства приведены примеры настройки этого шаблона рабочего процесса.

1. На GitHubперейдите на главную страницу репозитория.

2. Под именем репозитория щелкните **<svg version="1.1" width="16" height="16" viewBox="0 0 16 16" class="octicon octicon-play" aria-label="play" role="img"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path></svg> Actions**.

   ![Снимок экрана: вкладки для репозитория github/docs. Вкладка "Действия" выделена оранжевым контуром.](/assets/images/help/repository/actions-tab-global-nav-update.png)

3. Если в вашем репозитории уже используется рабочий процесс, нажмите кнопку **Создать рабочий процесс**.

4. На странице "Выбор рабочего процесса" показан выбор рекомендуемых шаблонов рабочих процессов. Поискайте «Python application».

5. В рабочем процессе "Python application" нажмите **Configure**.

   Если вы не нашли шаблон рабочего процесса "Python application", скопируйте следующий код рабочего процесса в новый файл под названием `python-app.yml` в каталоге `.github/workflows` вашего репозитория.

   ```yaml copy
   name: Python application

   on:
     push:
       branches: [ "main" ]
     pull_request:
       branches: [ "main" ]

   permissions:
     contents: read

   jobs:
     build:
       runs-on: ubuntu-latest

       steps:
       - uses: actions/checkout@v6
       - name: Set up Python 3.13
         uses: actions/setup-python@v5
         with:
           python-version: "3.13"
       - name: Install dependencies
         run: |
           python -m pip install --upgrade pip
           pip install ruff pytest
           if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
       - name: Lint and format Python code with ruff
         run: |
          # Lint with the default set of ruff rules with GitHub Annotations
          ruff check --format=github --target-version=py39
          # Verify the code is properly formatted
          ruff format --diff --target-version=py39
       - name: Test with pytest
         run: |
           pytest
   ```

6. Измените рабочий процесс по мере необходимости. Например, измените версию Python.

7. Щелкните **Зафиксировать изменения**.

## Определение версии на Python

Чтобы использовать предустановленную версию Python или PyPy на раннере с GitHub, используйте действие `setup-python`. Это действие находит определённую версию Python или PyPy из кэша инструментов на каждом раннере и добавляет необходимые бинарные файлы в `PATH`, который сохраняется на протяжении всей работы. Если конкретная версия Python не предустановлена в кэше инструментов, действие `setup-python` скачает и настроит соответствующую версию из репозитория [`python-versions`](https://github.com/actions/python-versions).

Рекомендуется использовать действие `setup-python` с Python с GitHub Actions, поскольку оно обеспечивает единообразное поведение между разными бегущими и разными версиями Python. Если вы используете самостоятельный раннер, обязательно установить Python и добавить его в `PATH`. Дополнительные сведения см. в описании [действия `setup-python`](https://github.com/marketplace/actions/setup-python).

В таблице ниже описаны расположения кэша инструментов в каждом GitHub-hosted runner.

<div class="ghd-tool rowheaders">

|                               | Ubuntu                          | Mac                                      | Windows                               |
| ----------------------------- | ------------------------------- | ---------------------------------------- | ------------------------------------- |
| **Каталог кэша инструментов** | `/opt/hostedtoolcache/*`        | `/Users/runner/hostedtoolcache/*`        | `C:\hostedtoolcache\windows\*`        |
| **Python Кэш инструментов**   | `/opt/hostedtoolcache/Python/*` | `/Users/runner/hostedtoolcache/Python/*` | `C:\hostedtoolcache\windows\Python\*` |
| **Кэш инструментов PyPy**     | `/opt/hostedtoolcache/PyPy/*`   | `/Users/runner/hostedtoolcache/PyPy/*`   | `C:\hostedtoolcache\windows\PyPy\*`   |

</div>

Если вы используете локальное средство выполнения, его можно настроить для управления зависимостями с помощью действия `setup-python`. Дополнительные сведения см. в разделе об [использовании setup-python с локальным средством выполнения](https://github.com/actions/setup-python#using-setup-python-with-a-self-hosted-runner) в файле сведений `setup-python`.

GitHub поддерживает синтаксис семантического версионирования. Дополнительные сведения см. в разделе ["Использование семантического управления версиями](https://docs.npmjs.com/about-semantic-versioning#using-semantic-versioning-to-specify-update-types-your-package-can-accept) " и [спецификации](https://semver.org/) семантического управления версиями.

### Использование нескольких версий Python

В следующем примере используется матрица для задания для настройки нескольких версий Python. Дополнительные сведения см. в разделе [Выполнение вариантов заданий в рабочем процессе](/ru/enterprise-server@3.22/actions/how-tos/write-workflows/choose-what-workflows-do/run-job-variations).

```yaml copy
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["pypy3.10", "3.9", "3.10", "3.11", "3.12", "3.13"]

    steps:
      - uses: actions/checkout@v6
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      # You can test your matrix by printing the current Python version
      - name: Display Python version
        run: python -c "import sys; print(sys.version)"
```

### Использование конкретной версии Python

Вы можете настроить определённую версию Python. Например, 3.12. Кроме того, можно использовать синтаксис семантической версии, чтобы получить последний дополнительный выпуск. В этом примере используется последняя небольшая версия Python 3.

```yaml copy
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v6
      - name: Set up Python
        # This is the version of the action for setting up Python, not the Python version.
        uses: actions/setup-python@v5
        with:
          # Semantic version range syntax or exact version of a Python version
          python-version: '3.x'
          # Optional - x64 or x86 architecture, defaults to x64
          architecture: 'x64'
      # You can test your matrix by printing the current Python version
      - name: Display Python version
        run: python -c "import sys; print(sys.version)"
```

### Исключение версии

Если указать версию Python, которая недоступна, `setup-python` выходит из строя с ошибкой, например: `##[error]Version 3.7 with arch x64 not found`. Сообщение об ошибке содержит доступные версии.

Вы также можете использовать ключевое слово `exclude` в вашем рабочем процессе, если есть конфигурация Python, которую вы не хотите запускать. Дополнительные сведения см. в разделе [Синтаксис рабочего процесса для GitHub Actions](/ru/enterprise-server@3.22/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idstrategy).

```yaml copy
name: Python package

on: [push]

jobs:
  build:

    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: ["3.9", "3.11", "3.13", "pypy3.10"]
        exclude:
          - os: macos-latest
            python-version: "3.11"
          - os: windows-latest
            python-version: "3.11"
```

### Использование стандартной версии Python

Рекомендуем использовать `setup-python` для настройки версии Python в ваших рабочих процессах, так как это помогает сделать зависимости явными. Если вы не используете `setup-python`, то стандартная версия Python, установленная в `PATH`, используется в любой оболочке, когда вы вызываете `python`. Стандартная версия Python варьируется между раннерами GitHub, что может вызвать неожиданные изменения или использовать более старую версию, чем ожидалось.

| GitHub- ведущий бегун | Description                                                                                                                                                                                                                                                                                                                                     |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Ubuntu                | В Ubuntu Runners установлены несколько версий системных Python под `/usr/bin/python` и `/usr/bin/python3`. Python версии, которые идут в комплекте с Ubuntu, дополняют версии, которые GitHub устанавливает в кэш инструментов.                                                                                                                 |
| Windows               | За исключением версий Python, которые находятся в кэше инструментов, Windows не поставляется с эквивалентной версией системного Python. Чтобы поддерживать согласованное поведение с другими раннерами и позволять использовать Python из коробки без действия `setup-python`, GitHub добавляет несколько версий из кэша инструментов в `PATH`. |
| macOS                 | На платформах для macOS установлено более одной версии системного Python, помимо версий, входящих в кэш инструментов. Версии Python системы расположены в каталоге `/usr/local/Cellar/python/*`.                                                                                                                                                |

## Установка зависимостей

GitHub-размещённые бегущие имеют установленный менеджер пакетов PIP. Вы можете использовать pip для установки зависимостей из реестра пакетов PyPI перед созданием и тестированием кода. Например, приведенный ниже код YAML устанавливает или обновляет установщик пакетов `pip` и пакеты `setuptools` и `wheel`.

Можно также кэшировать зависимости, чтобы ускорить рабочий процесс. Дополнительные сведения см. в разделе [Справочник по кэшированию зависимостей](/ru/enterprise-server@3.22/actions/reference/workflows-and-actions/dependency-caching).

```yaml copy
steps:
- uses: actions/checkout@v6
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
- name: Install dependencies
  run: python -m pip install --upgrade pip setuptools wheel
```

### Файл требований

После обновления `pip`типичный следующий шаг — установить зависимости из `requirements.txt`. Дополнительные сведения см. в описании [pip](https://pip.pypa.io/en/stable/cli/pip_install/#example-requirements-file).

```yaml copy
steps:
- uses: actions/checkout@v6
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
```

### Кэширование зависимостей

Можно кэшировать и восстанавливать зависимости с помощью [`setup-python`действия](https://github.com/actions/setup-python).

В следующем примере кэшируются зависимости для pip.

```yaml copy
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v5
  with:
    python-version: '3.12'
    cache: 'pip'
- run: pip install -r requirements.txt
- run: pip test
```

По умолчанию действие `setup-python` ищет файл зависимостей (`requirements.txt` для pip, `Pipfile.lock` для pipenv или `poetry.lock` для poetry) во всем репозитории. Дополнительные сведения см. в разделе [о зависимостях](https://github.com/actions/setup-python#caching-packages-dependencies) пакетов кэширования в `setup-python` README.

Если у вас есть особые требования или вам нужно управлять кэшированием более детально, можно использовать [действие `cache`](https://github.com/marketplace/actions/cache). Pip кэширует зависимости в разных расположениях в зависимости от операционной системы средства выполнения. Путь, по которому требуется выполнить кэширование, может отличаться от приведенного выше примера Ubuntu в зависимости от используемой операционной системы. Для получения дополнительной информации см. [Python примеры кэширования](https://github.com/actions/cache/blob/main/examples.md#python---pip) в репозитории действий `cache`.

## Тестирование кода

Вы можете использовать те же команды, которые используются для создания и тестирования кода в локальной среде.

### Тестирование с помощью pytest и pytest-cov

В этом примере устанавливаются или обновляются `pytest` и `pytest-cov`. Затем выполняются тесты, выходные данные выводятся в формате JUnit, а результаты по объему протестированного кода выводятся в Cobertura. Дополнительные сведения см. в описании [JUnit](https://junit.org/junit5/) и [Cobertura](https://cobertura.github.io/cobertura/).

```yaml copy
steps:
- uses: actions/checkout@v6
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
- name: Test with pytest
  run: |
    pip install pytest pytest-cov
    pytest tests.py --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html
```

### Использование Ruff для написания кода и (или) форматирования

В следующем примере выполняется установка или обновление `ruff` и его использование для анализа кода всех файлов. Дополнительные сведения см. в статье [Ruff](https://docs.astral.sh/ruff).

```yaml copy
steps:
- uses: actions/checkout@v6
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
- name: Install the code linting and formatting tool Ruff
  run: pipx install ruff
- name: Lint code with Ruff
  run: ruff check --output-format=github --target-version=py39
- name: Check code formatting with Ruff
  run: ruff format --diff --target-version=py39
  continue-on-error: true
```

Для шага `continue-on-error: true` форматирования задано значение. Это приведет к сбою рабочего процесса, если шаг форматирования не выполнен. После устранения всех ошибок форматирования можно удалить этот параметр, чтобы рабочий процесс перехватал новые проблемы.

### Выполнение тестов с помощью tox

С GitHub Actionsпомощью , можно проводить тесты с токсикологическими методами и распределять работу между несколькими работами. Вам нужно вызвать токсикологию с помощью опции `-e py`, чтобы выбрать версию Python в вашем `PATH`, вместо указания конкретной версии. Дополнительные сведения см. в описании [tox](https://tox.readthedocs.io/en/latest/).

```yaml copy
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python: ["3.9", "3.11", "3.13"]

    steps:
      - uses: actions/checkout@v6
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python }}
      - name: Install tox and any other packages
        run: pip install tox
      - name: Run tox
        # Run tox using the version of Python in `PATH`
        run: tox -e py
```

## Упаковка данных рабочего процесса в виде артефактов

Вы можете отправить артефакты для просмотра после завершения рабочего процесса. Например, может потребоваться сохранить файлы журналов, основные дампы, результаты теста или снимки экрана. Дополнительные сведения см. в разделе [Хранение и предоставление общего доступа к данным с артефактами рабочего процесса](/ru/enterprise-server@3.22/actions/tutorials/store-and-share-data).

В следующем примере показано, как использовать действие `upload-artifact` для архивации результатов теста при выполнении `pytest`. Дополнительные сведения см. в описании [действия `upload-artifact`](https://github.com/actions/upload-artifact).

```yaml copy
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

    steps:
      - uses: actions/checkout@v6
      - name: Setup Python # Set Python version
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      # Install pip and pytest
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pytest
      - name: Test with pytest
        run: pytest tests.py --doctest-modules --junitxml=junit/test-results-${{ matrix.python-version }}.xml
      - name: Upload pytest test results
        uses: actions/upload-artifact@v3
        with:
          name: pytest-results-${{ matrix.python-version }}
          path: junit/test-results-${{ matrix.python-version }}.xml
        # Use always() to always run this step to publish test results when there are test failures
        if: ${{ always() }}
```

## Публикация в PyPI

Вы можете настроить рабочий процесс так, чтобы публиковать пакет Python в PyPI после прохождения CI-тестов. В этом разделе показано, как вы можете GitHub Actions загружать свой пакет в PyPI каждый раз при публикации релиза. Дополнительные сведения см. в разделе [Управление выпусками в репозитории](/ru/enterprise-server@3.22/repositories/releasing-projects-on-github/managing-releases-in-a-repository).

В приведенном ниже примере рабочего процесса используется [надежная публикация](https://docs.pypi.org/trusted-publishers/) для проверки подлинности с помощью PyPI, что устраняет необходимость в маркере API, настроенном вручную.

```yaml copy
# Этот рабочий процесс использует действия, которые не сертифицированы GitHub.
# Они предоставляются сторонним поставщиком, и на них распространяются
# отдельные условия обслуживания, политика конфиденциальности и поддержка
# документации.

# GitHub рекомендует закрепить действия в фиксации SHA.
# Чтобы получить более новую версию, потребуется обновить SHA.
# Вы также можете ссылаться на тег или ветвь, однако действие может измениться без предупреждения.

name: Upload Python Package

on:
  release:
    types: [published]

permissions:
  contents: read

jobs:
  release-build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v6

      - uses: actions/setup-python@v5
        with:
          python-version: "3.x"

      - name: Build release distributions
        run: |
          # NOTE: put your own distribution build steps here.
          python -m pip install build
          python -m build

      - name: Upload distributions
        uses: actions/upload-artifact@v3
        with:
          name: release-dists
          path: dist/

  pypi-publish:
    runs-on: ubuntu-latest

    needs:
      - release-build

    permissions:
      # IMPORTANT: this permission is mandatory for trusted publishing
      id-token: write

    # Dedicated environments with protections for publishing are strongly recommended.
    environment:
      name: pypi
      # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status:
      # url: https://pypi.org/p/YOURPROJECT

    steps:
      - name: Retrieve release distributions
        uses: actions/download-artifact@v3
        with:
          name: release-dists
          path: dist/

      - name: Publish release distributions to PyPI
        uses: pypa/gh-action-pypi-publish@6f7e8d9c0b1a2c3d4e5f6a7b8c9d0e1f2a3b4c5d
```