Building and testing Python

Du kannst einen Workflow für kontinuierliche Integration (CI) erstellen, um Dein Python-Projekt zu bauen und zu testen.

Einführung

Diese Anleitung zeigt Dir, wie Du ein Python-Paket baust, testest und veröffentlichst.

For instructions on how to make sure your AE hosted runner has the required software installed, see "Creating custom images."

Vorrausetzungen

Du solltest mit YAML und der Syntax für GitHub Actions vertraut sein. For more information, see "Learn GitHub Actions."

Du solltest ein grundlegendes Verständnis von Python, PyPy und pip haben. Weitere Informationen findest Du unter:

Einstieg mit der Python-Workflow-Vorlage

GitHub bietet eine Python-Workflow-Vorlage, die für die meisten Python-Projekte funktionieren sollte. Diese Anleitung enthält Beispiele, mit denen Du die Vorlage anpassen kannst. For more information, see the Python workflow template.

Um schnell loszulegen, füge die Vorlage in das Verzeichnis .github/workflows Deines Repositorys ein.

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [3.6, 3.7, 3.8, 3.9]

    steps:
      - uses: actions/checkout@v2
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install flake8 pytest
          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
      - name: Lint with flake8
        run: |
          # stop the build if there are Python syntax errors or undefined names
          flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
          # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
          flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
      - name: Test with pytest
        run: |
          pytest

Eine Python-Version angeben

Benutze die Aktion setup-python, um eine vorinstallierte Version von Python oder PyPy auf einem GitHub-gehosteten Runner zu verwenden. Diese Aktion findet aus dem Tool-Cache auf jedem Runner eine bestimmte Version von Python oder PyPy und fügt die benötigten Binärdateien zum PATHhinzu, der für den Rest des Jobs bestehen bleibt. Wenn eine bestimmte Version von Python nicht im Tools-Cache vorinstalliert ist, lädt die Aktion setup-python die entsprechende Version vom Repository python-versions herunter und richtet sie ein.

Die setup-action ist die empfohlene Methode, Python mit GitHub Actions zu verwenden, da dadurch ein einheitliches Verhalten der verschiedenen Runner und verschiedenen Versionen von Python gewährleistet wird. Wenn Du einen selbst gehosteten Runner verwendest, musst Du Python installieren und zum PATH hinzufügen. Weitere Informationen findest Du in der Aktion setup-python.

Die folgende Tabelle zeigt für jeden GitHub-gehosteten Runner, wo der Tools-Cache liegt.

UbuntuMacWindows
Tool-Cache-Verzeichnis/opt/hostedtoolcache/*/Users/runner/hostedtoolcache/*C:\hostedtoolcache\windows\*
Tool-Cache für Python/opt/hostedtoolcache/Python/*/Users/runner/hostedtoolcache/Python/*C:\hostedtoolcache\windows\Python\*
Tool-Cache für PyPy/opt/hostedtoolcache/PyPy/*/Users/runner/hostedtoolcache/PyPy/*C:\hostedtoolcache\windows\PyPy\*

Wenn Du einen selbst gehosteten Runner verwendest, kannst Du den Runner so konfigurieren, dass er mithilfe der Aktion setup-python Deine Abhängigkeiten verwaltet. Weitere Informationen findest Du unter setup-python mit einem selbst-gehosteten Runner verwenden in der README von setup-python.

GitHub unterstützt dir Syntax für semantische Versionierung. Weitere Informationen findest Du unter „Semantische Versionierung verwenden“ und „Spezifikation für semantische Versionierung“.

Mehrere Python-Versionen verwenden

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      # Du kannst in python-version die PyPy-Versionen angeben,
      # For example, pypy2 and pypy3
      matrix:
        python-version: [2.7, 3.6, 3.7, 3.8, 3.9]

    steps:
      - uses: actions/checkout@v2
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        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)"

Eine bestimmten Python-Version verwenden

Du kannst eine bestimmte Version von Python konfigurieren, For example, 3.8. Alternatively, you can use semantic version syntax to get the latest minor release. Dieses Beispiel verwendet das neueste Minor Release von Python 3.

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - name: Set up Python 3.x
        uses: actions/setup-python@v2
        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)"

Eine Version ausschließen

Wenn du eine Version von Python angibst, die nicht verfügbar ist, schlägt setup-python fehl und meldet in etwa: ##[error]Version 3.4 with arch x64 not found. Die Fehlermeldung enthält die verfügbaren Versionen.

Du kannst in Deinem Workflow auch das Schlüsselwort exclude verwenden, wenn Du eine bestimmte Konfiguration von Python nicht laufen lassen möchtest. Weitere Informationen findest Du unter „Workflow-Syntax für GitHub Actions“.

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: [3.6, 3.7, 3.8, 3.9, pypy2, pypy3]
        exclude:
          - os: macos-latest
            python-version: 3.6
          - os: windows-latest
            python-version: 3.6

Die Standard-Version von Python verwenden

Wir empfehlen, setup-python zu verwenden, um die Version von Python zu konfigurieren, die in deinen Workflows verwendet wird, da es hilft, deine Abhängigkeiten explizit zu machen. Wenn du setup-python nicht verwendest, wird in jeder Shell, wenn Du python aufrufst, die Standardversion von Python verwendet, die in PATH gesetzt wurde. Die Standardversion von Python variiert zwischen den GitHub-gehosteten Runnern. Dies kann zu unerwarteten Abweichungen führen oder es kann unerwartet eine ältere Version verwendet werden.

GitHub-gehostete RunnerBeschreibung
UbuntuAuf Ubuntu-Runnern sind mehrere Versionen von System-Python unter /usr/bin/python und /usr/bin/python3 installiert. Die Python-Versionen, die mit Ubuntu mitgeliefert werden, sind zusätzlich zu den Versionen, die GitHub im Tools-Cache installiert.
WindowsNeben den Python-Versionen, die sich im Tools-Cache befinden, kommt Windows nicht mit einer entsprechenden Version von System-Python. Um das mit anderen Runnern konsistente Verhalten sicherzustellen und um Python „out-of-the-box“ ohne die Aktion setup-python nutzen zu können fügt GitHub ein paar Versionen aus dem Tools-Cache zum PATH hinzu.
macOSAuf macOS-Runnern sind zusätzlich zu den Versionen im Tool-Cache noch mehrere Versionen von System-Python installiert. Die Python-Versionen des Systems befinden sich im Verzeichnis /usr/local/Cellar/python/*.

Abhängigkeiten installieren

Auf GitHub-gehosteten Runnern ist der Paketmanager pip installiert. Du kannst pip verwenden, um Abhängigkeiten von der PyPI-Paket-Registry zu installieren, bevor Du Deinen Code baust und testest. Zum Beispiel installiert oder aktualisiert der folgende YAML den Paket-Installierer pip sowie die Pakete setuptools und wheel.

When using GitHub-hosted runners, you can also cache dependencies to speed up your workflow. Weitere Informationen findest Du unter „Abhängigkeiten zur Beschleunigung von Workflows im Cache zwischenspeichern“.

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

Datei für „Requirements“ (Anforderungen)

Nach dem Update von pip werden üblicherweise im nächsten Schritt die Abhängigkeiten aus requirements.txt installiert. For more information, see pip.

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

Abhängigkeiten im Cache zwischenspeichern

When using GitHub-hosted runners, you can cache pip dependencies using a unique key, and restore the dependencies when you run future workflows using the cache action. Weitere Informationen findest Du unter „Abhängigkeiten zur Beschleunigung von Workflows im Cache zwischenspeichern“.

Pip caches dependencies in different locations, depending on the operating system of the runner. The path you'll need to cache may differ from the Ubuntu example below depending on the operating system you use. For more information, see Python caching examples.

YAML
steps:
- uses: actions/checkout@v2
- name: Setup Python
  uses: actions/setup-python@v2
  with:
    python-version: '3.x'
- name: Cache pip
  uses: actions/cache@v2
  with:
    # This path is specific to Ubuntu
    path: ~/.cache/pip
    # Look to see if there is a cache hit for the corresponding requirements file
    key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
    restore-keys: |
      ${{ runner.os }}-pip-
      ${{ runner.os }}-
- name: Install dependencies
  run: pip install -r requirements.txt

Note: Depending on the number of dependencies, it may be faster to use the dependency cache. Projects with many large dependencies should see a performance increase as it cuts down the time required for downloading. Projects with fewer dependencies may not see a significant performance increase and may even see a slight decrease due to how pip installs cached dependencies. The performance varies from project to project.

Deinen Code testen

Du kannst die gleichen Befehle verwenden, die Du auch lokal verwendest, um Deinen Code zu erstellen und zu testen.

Mit pytest und pytest-cov testen

This example installs or upgrades pytest and pytest-cov. Tests are then run and output in JUnit format while code coverage results are output in Cobertura. For more information, see JUnit and Cobertura.

YAML
steps:
- uses: actions/checkout@v2
- name: Set up Python
  uses: actions/setup-python@v2
  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
    pip install pytest-cov
    pytest tests.py --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html

Mit Flake8 den Code von „Fusseln“ reinigen

The following example installs or upgrades flake8 and uses it to lint all files. For more information, see Flake8.

YAML
steps:
- uses: actions/checkout@v2
- name: Set up Python
  uses: actions/setup-python@v2
  with:
    python-version: '3.x'
- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
- name: Lint with flake8
  run: |
    pip install flake8
    flake8 .
  continue-on-error: true

The linting step has continue-on-error: true set. This will keep the workflow from failing if the linting step doesn't succeed. Once you've addressed all of the linting errors, you can remove this option so the workflow will catch new issues.

Tests mit Tox ausführen

With GitHub Actions, you can run tests with tox and spread the work across multiple jobs. You'll need to invoke tox using the -e py option to choose the version of Python in your PATH, rather than specifying a specific version. For more information, see tox.

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python: [3.7, 3.8, 3.9]

    steps:
      - uses: actions/checkout@v2
      - name: Setup Python
        uses: actions/setup-python@v2
        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

Workflow-Daten als Artefakte paketieren

You can upload artifacts to view after a workflow completes. Zum Beispiel kann es notwendig sein, Logdateien, Core Dumps, Testergebnisse oder Screenshots zu speichern. Weitere Informationen findest Du unter "Workflow-Daten mittels Artefakten persistieren."

The following example demonstrates how you can use the upload-artifact action to archive test results from running pytest. For more information, see the upload-artifact action.

YAML
name: Python package

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [3.6, 3.7, 3.8, 3.9]

    steps:
      - uses: actions/checkout@v2
      - name: Setup Python # Set Python version
        uses: actions/setup-python@v2
        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@v2
        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() }}

In Paket-Registries veröffentlichen

You can configure your workflow to publish your Python package to a package registry once your CI tests pass. This section demonstrates how you can use GitHub Actions to upload your package to PyPI each time you publish a release.

For this example, you will need to create two PyPI API tokens. You can use secrets to store the access tokens or credentials needed to publish your package. Weitere Informationen findest Du unter "Verschlüsselte Geheimnisse erstellen und verwenden".

YAML
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# dokumentation.

name: Upload Python Package

on:
  release:
    types: [published]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: '3.x'
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install build
      - name: Build package
        run: python -m build
      - name: Publish package
        uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
        with:
          user: __token__
          password: ${{ secrets.PYPI_API_TOKEN }}

For more information about the template workflow, see python-publish.

Did this doc help you?

Privacy policy

Help us make these docs great!

All GitHub docs are open source. See something that's wrong or unclear? Submit a pull request.

Make a contribution

Oder, learn how to contribute.