Ein praktischer Leitfaden zur Verwendung von Setup.py

Daten & KI-Schulungsleitfaden 2021

Laden Sie die GoDataDriven-Broschüre herunter, um einen vollständigen Überblick über die verfügbaren Schulungssitzungen und die Lernreisen für Data Engineering, Data Science, Datenanalysten und Analytiker zu erhalten.

Wenn Sie Python professionell einsetzen, zahlt es sich aus, Ihre Projekte
auf einheitliche Weise einzurichten. Das hilft Ihren Mitarbeitern, die
Struktur eines Projekts schnell zu verstehen, und macht es ihnen leichter, das Projekt
auf ihrem Rechner einzurichten. Der Schlüssel zum Einrichten Ihres Projekts ist die setup.pyDatei.
In diesem Blog werde ich auf die Details dieser Datei eingehen.

Wo wir anfangen

Hier nehme ich an, dass Sie bereits ein Paket haben, das Sie einrichten wollen.
Dies muss kein fertiges Paket sein – idealerweise sollten Sie die
setup.py erstellen, lange bevor Ihr Projekt fertig ist. Es kann sogar ein leeres Paket sein;
stell nur sicher, dass der Paketordner existiert
und eine Datei namens init.py enthält (die leer sein kann).

Wenn Sie der Struktur
meines Kollegen Henk für Ihr Projekt folgen, sollte Ihre Ausgangssituation etwa so aussehen:

example_project/├── exampleproject/ Python package with source code.│ ├── __init__.py Make the folder a package.│ └── example.py Example module.└── README.md README with info of the project.

Sie können andere Dateien oder Ordner in Ihrer Struktur haben, zum Beispiel
Ordner namens notebooks/, tests/ oder data/, aber diese sind nicht erforderlich.

Der Fall für ein setup.py

Wenn du ein Paket wie dieses erstellt hast, wirst du wahrscheinlich
einen Teil des Codes an anderen Stellen verwenden. Du könntest zum Beispiel
das in einem Notebook machen:

from exampleproject.example import example_function

Das würde funktionieren, wenn dein aktuelles Arbeitsverzeichnis example_project/ ist, aber in
allen anderen Fällen wird Python dir eine Ausgabe wie diese geben:

ModuleNotFoundError: No module named 'exampleproject'

Du könntest Python sagen, wo es nach dem Paket suchen soll, indem du die PYTHONPATH
Umgebungsvariable setzt oder den Pfad zu sys.pathhinzufügst,
aber das ist alles andere als ideal: Es würde verschiedene Aktionen auf verschiedenen
Plattformen erfordern, und der Pfad, den du setzen musst, hängt vom Ort deines Codes ab.
Ein viel besserer Weg ist es, dein Paket mit einer setup.py und pip zu installieren,
weil pip der Standardweg ist, um alle anderen Pakete zu installieren, und es ist verpflichtet
auf allen Plattformen gleich zu funktionieren.

Ein minimales Beispiel

Wie sieht also eine setup.py Datei aus? Hier ist ein minimales Beispiel0:

from setuptools import setup, find_packagessetup( name='example', version='0.1.0', packages=find_packages(include=))

Hier geben wir drei Dinge an:

  • Der Name des Pakets, das ist der Name, den pipIhr Paket verwenden wird.
    Dies muss nicht derselbe sein wie der Name des Ordners, in dem das Paket liegt
    , obwohl es verwirrend sein kann, wenn es nicht so ist. Ein Beispiel, bei dem der Paket
    name und das Verzeichnis nicht übereinstimmen, ist Scikit-Learn: Sie installieren es
    unter Verwendung von pip install scikit-learn, während Sie es durch Importieren von sklearn verwenden.
  • Die Version Ihres Pakets. Dies ist die Version, die pip melden wird, und wird
    z.B. verwendet, wenn du dein Paket auf PyPI1 veröffentlichst.
  • Welche Pakete eingeschlossen werden sollen; in unserem Fall ist dies nur exampleproject/.
    Hier lassen wir setuptools dies automatisch herausfinden
    2. Während man im Prinzip find_packages()
    ohne Argumente verwenden könnte, kann dies möglicherweise dazu führen, dass unerwünschte Pakete eingeschlossen werden
    . Dies kann zum Beispiel passieren,
    wenn Sie ein __init__.py in Ihr tests/
    Verzeichnis aufnehmen. Alternativ können Sie auch das excludeArgument verwenden, um explizit
    die Aufnahme von Tests in das Paket zu verhindern, aber dies ist etwas
    weniger robust.

Alles, was Sie nun tun müssen, um Ihr Paket zu installieren, ist, das Folgende
aus dem example_project/Verzeichnis3 auszuführen:

pip install -e .

Das . bezieht sich hier auf das aktuelle Arbeitsverzeichnis, von dem ich annehme, dass es das Verzeichnis
ist, in dem sich das setup.py befindet. Die -eFlagge gibt an, dass wir
im editierbaren Modus installieren wollen, was bedeutet,
dass wir, wenn wir die Dateien in unserem Paket bearbeiten, das
Paket nicht neu installieren müssen, bevor die Änderungen in Kraft treten. Du musst entweder
python neu starten oder das Paket neu laden!

Wenn du Informationen im setup.py selbst editierst, musst du das Paket in den meisten Fällen neu installieren
und auch wenn du neue (Unter-)Pakete hinzufügst.
Im Zweifelsfall kann es nie schaden, neu zu installieren. Führen Sie einfach pip install -e . erneut aus.

Anforderungen

Die meisten Projekte haben einige Abhängigkeiten. Sie haben höchstwahrscheinlich schon einmal eine
Anforderungen.txt
Datei verwendet, oder eine
Umgebung.yml
, wenn Sie conda verwenden. Nun, da Sie eine setup.py erstellen, können Sie Ihre
Abhängigkeiten im install_requiresArgument angeben.
Zum Beispiel können Sie für ein typisches Data Science-Projekt Folgendes haben:

setup( name='example', version='0.1.0', packages=find_packages(include=), install_requires=)

Sie können Anforderungen ohne eine Version (PyYAML) angeben, eine Version festlegen (pandas==0.23.3), eine minimale
Version angeben ('numpy>=1.14.5) oder einen Bereich von Versionen festlegen (matplotlib>=2.2.0,<3.0.0). Diese
Anforderungen werden automatisch von pip installiert, wenn Sie Ihr Paket installieren.

Extras-require

Manchmal gibt es Abhängigkeiten, die nur in bestimmten Situationen erforderlich sind. Als Datenwissenschaftler
erstelle ich oft Pakete, die ich zum Trainieren eines Modells verwende. Wenn ich an einem solchen Modell interaktiv arbeite
, kann es sein, dass ich matplotlib und jupyter installiert haben muss, um interaktiv mit den
Daten zu arbeiten und um Visualisierungen
der Leistung des Modells zu erstellen. Andererseits möchte ich, wenn das Modell in der Produktion läuft, weder matplotlib noch jupyter auf dem Rechner (oder Container) installieren, auf dem ich trainiere
oder Inferenzen durchführe. Glücklicherweise erlaubt setuptools die Angabe von optionalen Abhängigkeiten in extras_require:

setup( name='example', version='0.1.0', packages=find_packages(include=), install_requires=, extras_require={ 'interactive': , })

Wenn wir nun das Paket normal installieren (pip install example von PyPI oder pip install -e . lokal)
wird es nur die Abhängigkeiten PyYAML, pandas und numpy installieren. Wenn wir jedoch
angegeben haben, dass wir die optionalen interactiveAbhängigkeiten (pip install example
oder pip install -e .) haben wollen,
dann werden auch matplotlib und jupyter installiert.

Skripte und Einstiegspunkte

Der Hauptanwendungsfall der meisten Python-Pakete, die man von PyPI installiert, ist die Bereitstellung von Funktionalität
, die in anderem Python-Code verwendet werden kann. Mit anderen Worten, man kann import von diesen Paketen profitieren.
Als Datenwissenschaftler erstelle ich oft Pakete, die nicht dazu gedacht sind, von anderem Python-Code verwendet zu werden, sondern
etwas zu tun, zum Beispiel ein Modell zu trainieren. Als solches habe ich oft ein Python-Skript, das
ich von der Kommandozeile aus ausführen möchte.

Der beste Weg4 , um die Funktionalität deines Pakets auf der Kommandozeile auszuführen, ist, ein
ein entry_point wie folgt zu definieren:

setup( # ..., entry_points={ 'console_scripts': })

Jetzt kannst du den Befehl my-command von der Kommandozeile aus verwenden, der wiederum die main
Funktion innerhalb von exampleproject/example.py ausführt. Vergessen Sie nicht, neu zu installieren – sonst wird der Befehl
nicht registriert.

Tests

Wenn Sie irgendeinen Code schreiben, empfehle ich Ihnen dringend, auch Tests für diesen Code zu schreiben. Für Tests
mit Python schlage ich vor, pytest zu verwenden. Natürlich willst du pytest nicht zu deinen Abhängigkeiten
in install_requires hinzufügen: es wird von den Benutzern deines Pakets nicht benötigt. Damit es
automatisch installiert wird, wenn du Tests ausführst, kannst du folgendes zu deinem setup.py hinzufügen:

setup( # ..., setup_requires=, tests_require=,)

Zusätzlich musst du eine Datei mit dem Namen setup.cfg mit folgendem Inhalt erstellen:

test=pytest

Jetzt kannst du einfach python setup.py test ausführen und setuptools stellt sicher, dass die notwendigen Abhängigkeiten
installiert sind und pytest für dich ausgeführt wird! Schauen Sie hier nach, wenn
Sie Argumente bereitstellen oder Konfigurationsoptionen für pytest einstellen möchten.

Wenn Sie zusätzliche Anforderungen für das Testen haben (z.B. pytest-flask), können Sie diese zu tests_require hinzufügen.

Flake8

Persönlich denke ich, dass es eine gute Idee ist, Flake8 auszuführen, um
die Formatierung Ihres Codes zu überprüfen. Genau wie bei pytest solltest du flake8 nicht zu den
install_requires Abhängigkeiten hinzufügen: es muss nicht installiert sein, um dein
Paket zu benutzen. Stattdessen kannst du es zu setup_requires:

setup( # ..., setup_requires=)

hinzufügen. Jetzt kannst du einfach python setup.py flake8 ausführen. Natürlich kannst du auch die Version
von flake8 (oder jedem anderen Paket) in setup_requires.

Wenn du einige der Konfigurationsparameter von Flake8 ändern möchtest, kannst du einen Abschnitt zu
deinem setup.cfg hinzufügen. Zum Beispiel:

max-line-length=120

Paketdaten

Gelegentlich möchten Sie vielleicht einige Nicht-Python-Dateien in Ihr Paket aufnehmen. Diese
können zum Beispiel Schemadateien oder eine kleine Nachschlagetabelle sein. Seien Sie sich bewusst, dass solche Dateien
zusammen mit Ihrem Code gepackt werden, also ist es im Allgemeinen eine schlechte Idee,
große Dateien einzubinden.

Angenommen, wir haben ein schema.json in unserem Projekt, das wir in exampleproject/data/schema.json platzieren.
Wenn wir sie in unser Paket aufnehmen wollen, müssen wir das package_data-Argument von setup verwenden:

setup( # ..., package_data={'exampleproject': })

Damit wird sichergestellt, dass die Datei in das Paket aufgenommen wird. Wir können auch wählen, ob wir
alle Dateien basierend auf einem Muster einschließen wollen, zum Beispiel:

setup( # ..., package_data={'': })

Dies fügt alle *.json Dateien in jedes Paket ein, auf das es trifft.

Versuchen Sie jetzt nicht, den Ort der installierten Dateien selbst herauszufinden, denn
pkg_resources hat einige sehr praktische Komfortfunktionen:

  • pkg_resources.resource_stream gibt dir einen Stream der Datei, ähnlich wie das
    Objekt, das du bekommst, wenn du open() aufrufst,
  • pkg_resources.resource_string gibt dir den Inhalt der Datei als String,
  • pkg_resources.resource_filename gibt Ihnen den Dateinamen der Datei (und extrahiert
    sie in ein temporäres, wenn sie in einem gepackten Paket enthalten ist), wenn die beiden obigen Optionen
    nicht Ihren Bedürfnissen entsprechen.

Zum Beispiel könnten wir unser Schema wie folgt einlesen:

from json import loadfrom pkg_resources import resource_streamschema = load(resource_stream('exampleproject', 'data/schema.json'))

Metadaten

Wenn Sie Ihr Paket veröffentlichen wollen, dann wollen Sie wahrscheinlich Ihren
potentiellen Nutzern einige weitere Informationen über Ihr Paket geben, einschließlich einer Beschreibung,
dem Namen des Autors oder Betreuers und der URL zur Homepage des Pakets.
Eine vollständige Liste aller erlaubten Metadaten finden Sie in den setuptools
Dokumenten.

Zusätzlich, wenn du in PyPI veröffentlichen willst, dann möchtest du vielleicht
automatisch den Inhalt deines README.md
in die long_description laden,
und Klassifizierer bereitstellen, um pipmehr über dein Paket zu erzählen.

Wrap-up

Dieser Blog sollte ein guter Startpunkt sein, um die meisten deiner Python-Projekte einzurichten.
Wenn du mehr über Python-Packaging lesen willst, schau dir die Docs an. Hier ist ein Beispiel setup.py
, das alle in diesem Blog gezeigten Teile kombiniert:

from setuptools import setup, find_packagessetup( name='example', version='0.1.0', description='Setting up a python package', author='Rogier van der Geer', author_email='[email protected]', url='https://blog.godatadriven.com/setup-py', packages=find_packages(include=), install_requires=, extras_require={'plotting': }, setup_requires=, tests_require=, entry_points={ 'console_scripts': }, package_data={'exampleproject': })

und das dazugehörige setup.cfg:

test=pytestmax-line-length=120

Verbessern Sie Ihre Python-Kenntnisse, lernen Sie von den Experten!

Bei GoDataDriven bieten wir eine Vielzahl von Python-Kursen an, vom Anfänger bis zum Experten, die von den besten Fachleuten auf diesem Gebiet unterrichtet werden. Machen Sie mit und verbessern Sie Ihre Python-Kenntnisse:

  • Python Essentials – Ideal, wenn Sie gerade erst mit Python anfangen.
  • Certified Data Science with Python Foundation – Möchten Sie den Schritt von der Datenanalyse und -visualisierung zu echter Datenwissenschaft machen? Dies ist der richtige Kurs.
  • Advanced Data Science with Python – Lernen Sie, Ihre Modelle wie ein Profi zu produzieren und Python für maschinelles Lernen zu verwenden.
Fußnoten

0: In diesem Blog habe ich setuptools
verwendet, um mein Beispielprojekt einzurichten. Alternativ
könnte man auch distutils verwenden,
das das Standardwerkzeug für das Paketieren in Python ist, aber ihm fehlen Features
wie die Funktion find_packages() und entry_points.
Da die Verwendung von setuptools heutzutage sehr verbreitet ist und viele seiner Funktionen
besonders nützlich sein können, schlage ich vor, dass du setuptools verwendest.

1: Wenn du möchtest, dass die Version deines Pakets auch innerhalb von Python verfügbar ist,
habe einen Blick darauf.

2: Du könntest deine Pakete auch manuell auflisten, aber das ist besonders fehleranfällig.

3: Alternativ könntest du python setup.py install ausführen, aber die Verwendung von pip hat
viele Vorteile, darunter die automatische Installation von Abhängigkeiten und die
Möglichkeit, dein Paket zu deinstallieren oder zu aktualisieren.

4: Sie könnten auch das Argument scripts verwenden (siehe zum
Beispiel hier)
aber da dies erfordert, dass Sie ein Python-Shell-Skript erstellen, könnte es nicht
so gut (oder überhaupt) unter Windows funktionieren.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.