Upload

Schließlich solltet ihr das Paket auf dem Python Package Index (PyPI) oder einem anderen Index bereitstellen.

Hierfür solltet 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:

$ pipenv update pip pep517 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. Die restlichen Build-Tools werden von pep517 automatisch in der isolierten Build-Umgebung installiert.

Nun könnt ihr eure Distribution Packages erstellen mit:

$ rm -rf build dist
$ pipenv run python -m pep517.build .

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

$ pipenv run 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 pipenv 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:

$ mkdir test
$ cd !$
$ pipenv install --extra-index-url 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:

Collecting example_pkg
  Downloading https://test-files.pythonhosted.org/packages/.../minimal_example-0.0.1-py3-none-any.whl
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:

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

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

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:

$ pipenv run 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 === explizit 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:

name: pypi
on:
  push:
    tags:
    - '*'

jobs:
  package-and-deploy:

    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: 3.8

      - name: Install dependencies
        run: |
          python -m pip install -U pip
          python -m pip install -U setuptools twine wheel

      - name: Build and publish
        env:
          TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
          TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
        run: |
          python setup.py sdist bdist_wheel
          twine upload dist/*

Siehe auch