Vor etwa drei Jahren schrieb ich einen Blogbeitrag über die Verwendung von setup.py zum Einrichten Ihrer Python-Projekte. Seitdem hat sich viel geändert, vor allem durch PEP 517, PEP 518 und die Einführung der Datei pyproject.toml.
Das Ziel dieser Datei ist es, Ihnen zu ermöglichen, zu definieren, welche Build-Tools benötigt werden, um Ihr Paket zu bauen - und nicht mehr davon auszugehen, dass es Setuptools sein muss. Dies macht es einfacher, Alternativen zu Setuptools zu verwenden, was bedeutet, dass Setuptools nicht mehr das einzige Build-Tool sein muss, das alles kann.
Nichtsdestotrotz gefällt mir der Funktionsumfang von Setuptools und ich würde es gerne in absehbarer Zukunft weiter verwenden. Aber während die Dokumentation für die Verwendung von z.B. Poetry oder Flit zusammen mit pyproject.toml leicht zu finden ist, ist es schwieriger, eine ähnliche Dokumentation für Setuptools zu finden. Lassen Sie mich Ihnen also helfen.
Die Datei pyproject.toml
Die pyproject.toml definiert, welche Build-Tools für die Erstellung unseres Pakets benötigt werden. Das kann ziemlich einfach sein:
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
Das ist alles, was es zu sagen gibt! Während Alternativen wie Poetry und Flit die Paketinformationen ebenfalls in dieser Datei definieren, legt Setuptools diese in einer separaten Datei ab.
Wenn Sie das Bedürfnis haben, die Version von Setuptools einzuschränken, die verwendet werden kann, können Sie dies natürlich wie requires = ["setuptools>=40.6.0"] tun.
Die Datei setup.cfg
Dies ist der Ort, an dem alle Konfigurationsdetails Ihres Pakets abgelegt werden. Diese wurden früher in setup.py abgelegt (obwohl man in der Vor-PEP 517-Ära auch setup.cfg verwenden konnte), aber wie Sie sehen werden, ist die deklarative Konfiguration in setup.cfg praktischer.
Lassen Sie uns nun mit einem einfachen Beispiel beginnen:
[metadata]
name = example
version = 0.1.0
[options]
packages = find:
Dies definiert Ihr Paket mit dem Namen example, mit der Version 0.1.0. Das ist alles, was Sie brauchen!
Projektstruktur
Die Struktur Ihres Projekts sollte folgendermaßen aussehen:
/path/to/example/project/
├── example/ Python package directory.
│ ├── __init__.py This makes the directory a package.
│ └── example_module.py An example module.
├── pyproject.toml Definition of build process of the package.
├── README.md README with info of the project.
└── setup.cfg Configuration details of the python package.
Natürlich können Sie auch andere Dateien oder Ordner in der Struktur haben, wie z.B. einen tests/ Ordner, eine .gitignore oder eine LICENSE Datei, aber diese sind nicht unbedingt erforderlich.
Nun können Sie Ihr Paket erstellen, indem Sie python -m build --wheel in dem Ordner ausführen, in dem sich pyproject.toml befindet. (Möglicherweise müssen Sie das build Paket zuerst: pip install build.) Dies sollte eine build/ Ordner sowie einen dist/ Ordner (vergessen Sie nicht, diese zu Ihrem .gitignore(falls sie dort nicht schon vorhanden sind!), in dem Sie ein Rad mit dem folgenden Namen finden example-0.1.0-py3-none-any.whl. Diese Datei enthält Ihr Paket, und das ist alles, was Sie brauchen, um es zu verteilen. Sie können dieses Paket überall installieren, indem Sie es auf den entsprechenden Rechner kopieren und pip install example-0.1.0-py3-none-any.whl ausführen.
Wenn Sie entwickeln, möchten Sie wahrscheinlich nicht jedes Mal, wenn Sie eine Änderung am Code vorgenommen haben, das Rad neu bauen und neu installieren. Damit wird Ihr Paket installiert, ohne es in eine Datei zu packen, sondern indem Sie auf das Quellverzeichnis verweisen. Führen Sie dazu pip install -e . aus dem Verzeichnis aus, in dem sich die pyproject.toml befindet. Alle Änderungen, die Sie am Quellcode vornehmen, werden sofort wirksam. Beachten Sie jedoch, dass Sie möglicherweise Ihr Python-Programm auslösen müssen, um den Code erneut zu importieren, indem Sie entweder Ihre Python-Sitzung neu starten oder zum Beispiel das setup.cfg) erst nach einer Neuinstallation mit pip install -e . wirksam werden.
Weitere Optionen
Setuptools verfügt über eine ganze Reihe von Optionen, die wir hinzufügen können. Schauen wir uns ein paar davon an.
Abhängigkeiten
Die Abhängigkeiten Ihres Pakets können im Abschnitt install_requires der Optionen angegeben werden:
[options]
install_requires =
pandas == 1.4.1
PyYAML >= 6.0
typer
Wenn Sie irgendwelche Abhängigkeiten haben, die nur in manchen Fällen benötigt werden, können Sie diese als extras_require hinzufügen:
[options.extras_require]
notebook = jupyter>=1.0.0, matplotlib
dev =
black==22.1.0
flake8==4.0.1
Diese Abhängigkeiten werden nur installiert, wenn Sie danach fragen, z.B. pip install -e ".[dev]" oder pip install "example-0.1.0-py3-none-any.whl[dev,notebook]". Vergessen Sie nicht, den Paketnamen in diesen Befehlen anzugeben!
Einstiegspunkte
Wenn Sie Funktionen in Ihrem Paket haben, die Sie als Kommandozeilenprogramm verwenden möchten, können Sie diese zu den console_scripts Einstiegspunkten hinzufügen. Wenn Sie z.B. eine Funktion namens main in example_module.py haben, dann können Sie diese Funktion zu setup.cfg hinzufügen, damit Benutzer my-example-utility als Shell-Befehl ausführen können:
[options.entry_points]
console_scripts =
my-example-utility = example.example_module:main
Oder, wenn Sie z.B. typer verwenden und eine cli.py mit folgendem Inhalt haben:
from typer import Typer
app = Typer()
@app.command()
def hello():
print("Hello.")
@app.command()
def bye(name: str):
print(f"Bye {name}")
dann hinzufügen
[options.entry_points]
console_scripts =
example-tool = example.cli:app
ermöglicht es Ihnen, Befehle wie example-tool hello und example-tool bye rogier auszuführen.
Ein src/ Layout
Viele Leute ziehen es vor, ihre Python-Pakete in einem Ordner src/ in ihrem Projektverzeichnis abzulegen, was bedeutet, dass sie eine Projektstruktur wie diese haben:
/path/to/example/project/
├── src/ Source dir.
│ └── example/ Python package directory.
│ ├── __init__.py This makes the directory a package.
│ └── example_module.py Example module.
├── pyproject.toml Definition of build process of the package.
├── README.md README with info of the project.
└── setup.cfg Configuration details of the python package.
Sie können dies tun, indem Sie die folgenden Optionen zu Ihrer Paketkonfiguration hinzufügen:
[options]
package_dir=
=src
[options.packages.find]
where=src
Paketdaten
Standardmäßig werden nur .py Dateien in Ihrem Paketordner zu den Rädern hinzugefügt, die Sie bauen. Wenn Sie andere Dateien einschließen möchten, z. B. Daten, die Ihr Paket benötigt, können Sie diese als solche hinzufügen:
[options]
zip_safe = True
include_package_data = True
[options.package_data]
example = data/schema.json, *.txt
* = README.md
Dies weist Setuptools an, die Datei example/data/schema.json sowie alle .txt Dateien, die sich in Ihrem Beispielpaket befinden, einzubinden. Außerdem wird Setuptools angewiesen, alle README.md Dateien in allen Paketen einzuschließen, die es findet (falls Sie mehrere Pakete in Ihrem Projektordner haben).
Normalerweise werden Python-Pakete als Zip-Dateien installiert, was bedeutet, dass ihr Quellcode nicht als Dateien im Dateisystem verfügbar ist. Das Flag
from json import load
from pkg_resources import resource_stream
def load_schema():
return load(resource_stream("example", "data/schema.json"))
Dies funktioniert auch, wenn Ihr Paket als Zip-Datei installiert ist.
Metadaten
Vielleicht möchten Sie mehr Informationen über Ihr Paket angeben als nur einen Namen und eine Version. Hier ist ein Beispiel für einige verfügbare Optionen:
[metadata]
name = example
version = attr: example.__version__
author = You
author_email = your@email.address
url = https://xebia.com/blog/a-practical-guide-to-setuptools-and-pyproject-toml
description = Example package description
long_description = file: README.md
long_description_content_type = text/markdown
keywords = example, setuptools
license = BSD 3-Clause License
classifiers =
License :: OSI Approved :: BSD License
Programming Language :: Python :: 3
Beachten Sie, dass in diesem Beispiel zwei spezielle Direktiven verwendet werden: Der Inhalt von README.md wird als lange Beschreibung verwendet, indem die Direktive file: verwendet wird, und die Version des Pakets wird aus der Variable version gelesen, die in example/init.py definiert ist. Dieses letzte Kunststück war früher bei der Verwendung von setup.pyziemlich kompliziert.
Einpacken
Wenn Sie Setuptools und pyproject.toml verwenden möchten, um Ihr Paket zu erstellen, sollte dies ein guter Ausgangspunkt für Sie sein:
pyproject.toml
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
setup.cfg
[metadata]
name = example
version = attr: example.__version__
author = You
author_email = your@email.address
url = https://xebia.com/blog/a-practical-guide-to-setuptools-and-pyproject-toml
description = Example package description
long_description = file: README.md
long_description_content_type = text/markdown
keywords = example, setuptools
license = BSD 3-Clause License
classifiers =
License :: OSI Approved :: BSD License
Programming Language :: Python :: 3
[options]
packages = find:
zip_safe = True
include_package_data = True
install_requires =
pandas == 1.4.1
PyYAML >= 6.0
typer
[options.entry_points]
console_scripts =
my-example-utility = example.example_module:main
[options.extras_require]
notebook = jupyter>=1.0.0, matplotlib
dev =
black==22.1.0
flake8==4.0.1
[options.package_data]
example = data/schema.json, *.txt
* = README.md
Erstellen Sie nun Ihr Projekt, indem Sie pip -m build . --wheel ausführen, oder führen Sie eine editierbare Installation mit pip install -e . durch. Weitere Einzelheiten zu den verfügbaren Optionen von setup.cfg finden Sie in den Dokumentationen.
Verfasst von
Rogier van der Geer
Unsere Ideen
Weitere Blogs
Contact



