Paket hochladen#

Schließlich könnt ihr das Paket auf dem Python Package Index (PyPI) oder einem anderen Index, z.B. GitLab Package Registry oder devpi, bereitstellen.

Hierfür müsst ihr euch bei Test PyPI registrieren. Test-PyPI ist eine separate Instanz, die zum Testen und Experimentieren vorgesehen ist. Um dort ein Konto einzurichten, geht ihr auf https://test.pypi.org/account/register/. Weitere Informationen findet ihr unter Using TestPyPI.

Nun könnt ihr eine ~/.pypirc-Datei erstellen:

[distutils]
index-servers=
    test

[test]
repository = https://test.pypi.org/legacy/
username = veit

Siehe auch

Wenn ihr die PyPI-Anmeldung automatisieren wollt, lest bitte Careful With That PyPI.

Nachdem ihr registriert seid, könnt ihr euer Distribution Package mit twine hochladen. Hierzu müsst ihr jedoch zunächst twine installieren mit:

$ python -m pip install --upgrade pip build twine

All dependencies are now up-to-date!

Bemerkung

Führt diesen Befehl vor jedem Release aus um sicherzustellen, dass alle Release-Tools auf dem neuesten Stand sind.

Nun könnt ihr eure Distribution Packages erstellen mit:

$ cd /path/to/your/distribution_package
$ rm -rf build dist
$ pyproject-build .

Nach der Installation von Twine könnt ihr alle Archive unter /dist auf den Python Package Index hochladen mit:

$ twine upload -r test -s dist/*
-r, --repository

Das Repository zum Hochladen des Pakets.

In unserem Fall wird test-Abschnitt aus der ~/.pypirc-Datei verwendet.

-s, --sign

signiert die hochzuladenden Dateien mit GPG.

Ihr werdet nach eurem Passwort gefragt, mit dem ihr euch bei Test PyPI registriert habt. Anschließend solltet ihr eine ähnliche Ausgabe sehen:

Uploading distributions to https://test.pypi.org/legacy/
Enter your username: veit
Enter your password:
Uploading example-0.0.1-py3-none-any.whl
100%|█████████████████████| 4.65k/4.65k [00:01<00:00, 2.88kB/s]
Uploading example-0.0.1.tar.gz
100%|█████████████████████| 4.25k/4.25k [00:01<00:00, 3.05kB/s]

Bemerkung

Wenn ihr eine ähnliche Fehlermeldung erhaltet wie

The user 'veit' isn't allowed to upload to project 'example'

müsst ihr einen eindeutigen Namen für euer Paket auswählen:

  1. ändert das name-Argument in der setup.py-Datei

  2. entfernt das dist-Verzeichnis

  3. generiert die Archive neu

Überprüfen#

Installation#

Ihr könnt pip verwenden um euer Paket zu installieren und zu überprüfen, ob es funktioniert. Erstellt eine neue virtuelle Umgebung und installiert euer Paket von Test PyPI:

$ python3 -m venv test_env
$ source test_env/bin/activate
$ pip install -i https://test.pypi.org/simple/ minimal_example

Bemerkung

Wenn ihr einen anderen Paketnamen verwendet habt, ersetzt ihn im obigen Befehl durch euren Paketnamen.

pip sollte das Paket von Test PyPI installieren und die Ausgabe sollte in etwa so aussehen:

Looking in indexes: https://test.pypi.org/simple/
Collecting minimal_example

Installing collected packages: minimal_example
Successfully installed minimal_example-0.0.1

Ihr könnt testen, ob euer Paket korrekt installiert wurde indem ihr das Modul importiert und auf die name-Eigenschaft referenziert, die zuvor in __init__.py eingegeben wurde:

$ python
Python 3.7.0 (default, Aug 22 2018, 15:22:29)

>>> import minimal_example
>>> minimal_example.name
'minimal_example'

Bemerkung

Die Pakete auf Test-PyPI werden nur temporär gespeichert. Wenn ihr ein Paket in den echten Python Package Index (PyPI) hochladen wollt, könnt ihr dies tun, indem ihr ein Konto auf pypi.org anlegt und die gleichen Anweisungen befolgt, jedoch twine upload dist/* verwendet.

README#

Überprüft bitte auch, ob die README.rst-Datei auf der Test-PyPI-Seite korrekt angezeigt wird.

PyPI#

Registriert euch nun beim Python Package Index (PyPI) und stellt sicher, dass die Zwei-Faktor-Authentifizierung aktiviert ist indem ihr die ~/.pypirc-Datei ergänzt:

[distutils]
index-servers=
    pypi
    test

[test]
repository = https://test.pypi.org/legacy/
username = veit

[pypi]
username = __token__

Mit dieser Konfiguration wird nicht mehr die Name/Passwort-Kombination beim Hochladen verwendet sondern ein Upload-Token.

Schließlich könnt ihr nun euer Paket auf PyPI veröffentlichen:

$ twine upload -r pypi -s dist/*

Bemerkung

Ihr könnt Releases nicht einfach ersetzen da ihr Pakete mit derselben Versionsnummer nicht erneut hochladen könnt.

Bemerkung

Entfernt nicht alte Versionen aus dem Python Package Index. Dies verursacht nur Arbeit für jene, die diese Version weiter verwenden wollen und dann auf alte Versionen auf GitHub ausweichen müssen. PyPI hat eine yank-Funktion, die ihr stattdessen nutzen könnt. Dies ignoriert eine bestimmte Version, wenn sie nicht explizit mit == oder === angegeben wurde.

GitHub Action#

Ihr könnt auch eine GitHub-Aktion erstellen, die ein Paket erstellt und auf PyPI hochlädt. Eine solche .github/workflows/pypi.yml-Datei könnte folgendermaßen aussehen:

 1name: Publish Python Package
 2
 3 on:
 4   release:
 5     types: [created]
 6
 7jobs:
 8  test:
 9    
10  package-and-deploy:
11    runs-on: ubuntu-latest
12    needs: [test]
13    steps:
14    - name: Checkout
15      uses: actions/checkout@v2
16      with:
17        fetch-depth: 0
18    - name: Set up Python
19      uses: actions/setup-python@v5
20      with:
21        python-version: '3.11'
22        cache: pip
23        cache-dependency-path: '**/pyproject.toml'
24    - name: Install dependencies
25      run: |
26        python -m pip install -U pip
27        python -m pip install -U setuptools build twine wheel
28    - name: Build
29      run: |
30        python -m build
31    - name: Publish
32      env:
33        TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
34        TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
35      run: |
36        twine upload dist/*
Zeilen 3–5

Dies stellt sicher, dass der Arbeitsablauf jedes Mal ausgeführt wird, wenn ein neues GitHub-Release für das Repository erstellt wird.

Zeile 12

Der Job wartet auf das Bestehen des test-Jobs bevor er ausgeführt wird.

Trusted Publishers#

Trusted Publishers ist ein alternatives Verfahren zum Veröffentlichen von Paketen auf dem PyPI. Sie basiert auf OpenID Connect und erfordert weder Passwort noch Token. Dazu sind lediglich die folgenden Schritte erforderlich:

  1. Fügt einen Trusted Publishers auf PyPI hinzu

    Je nachdem, ob ihr ein neues Paket veröffentlichen oder ein bestehendes aktualisieren wollt, unterscheidet sich der Prozess geringfügig:

    • zum Aktualisieren eines bestehenden Pakets siehe Adding a trusted publisher to an existing PyPI project

    • zum veröffentlichen eines neuen Pakets gibt es ein spezielles Verfahren, Pending Publisher genannt; s.a. Creating a PyPI project with a trusted publisher

      Ihr könnt damit auch einen Paketnamen reservieren, bevor ihr die erste Version veröffentlicht. Damit könnt ihr sicherstellen, dass ihr das Paket auch unter dem gewünschten Namen veröffentlichen könnt.

      Hierfür müsst ihr in pypi.org/manage/account/publishing/ einen neuen Pending Publisher erstellen mit

      • Namen des PyPI-Projekts

      • GitHub-Repository Owner

      • Namen des Workflows, z.B. publish.yml

      • Name der Umgebung (optional), z.B. release

  2. Erstellt eine Umgebung für die GitHub-Actions

    Wenn wir eine Umgebung auf PyPI angegeben haben, müssen wir diese nun auch erstellen. Das kann in Settings ‣ Environments für das Repository geschehen. Der Name unserer Umgebung ist release.

  3. Konfiguriert den Arbeitsablauf

    Hierfür erstellen wir nun die Datei .github/workflows/publish.yml in unserem Repository:

     1
     2jobs:
     3  
     4  deploy:
     5    runs-on: ubuntu-latest
     6    environment: release
     7    permissions:
     8      id-token: write
     9    needs: [test]
    10    steps:
    11    - name: Checkout
    12      
    13    - name: Set up Python
    14      
    15    - name: Install dependencies
    16      
    17    - name: Build
    18      
    19    - name: Publish
    20      uses: pypa/gh-action-pypi-publish@release/v1
    
    Zeile 6

    Dies wird benötigt, weil wir eine Umgebung in PyPI konfiguriert haben.

    Zeilen 7–8

    Sie sind erforderlich, damit die OpenID Connect-Token-Authentifizierung funktioniert.

    Zeilen 19–20

    Das Paket verwendet die Aktion github.com/pypa/gh-action-pypi-publish, um das Paket zu veröffentlichen.