PYTHONPATH vs. sys.path

91

Ein anderer Entwickler und ich sind uns nicht einig, ob PYTHONPATH oder sys.path verwendet werden sollen, damit Python ein Python-Paket in einem Benutzerverzeichnis (z. B. Entwicklungsverzeichnis) finden kann.

Wir haben ein Python-Projekt mit einer typischen Verzeichnisstruktur:

Project
    setup.py
    package
        __init__.py
        lib.py
        script.py

In script.py müssen wir tun import package.lib. Wenn das Paket in Site-Paketen installiert ist, kann script.py finden package.lib.

Bei der Arbeit in einem Benutzerverzeichnis muss jedoch noch etwas anderes getan werden. Meine Lösung besteht darin, meinen PYTHONPATH so einzustellen, dass er "~ / Project" enthält. Ein anderer Entwickler möchte diese Codezeile am Anfang von script.py einfügen:

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

Damit Python die lokale Kopie von finden kann package.lib.

Ich denke, dies ist eine schlechte Idee, da diese Zeile nur für Entwickler oder Leute nützlich ist, die mit einer lokalen Kopie arbeiten, aber ich kann keinen guten Grund nennen, warum es eine schlechte Idee ist.

Sollten wir PYTOHNPATH, sys.path oder entweder in Ordnung verwenden?

gaefan
quelle
4
Es scheint, dass die Stimmen und Antworten ziemlich gleichmäßig verteilt sind, mit einer sehr geringen Neigung zur Verwendung von PYTHON_PATH, obwohl dies Rauschabtastung oder unbeabsichtigte Verzerrung der Frage sein könnte.
AJP

Antworten:

42

Wenn der einzige Grund für die Änderung des Pfads darin besteht, dass Entwickler von ihrem Arbeitsbaum aus arbeiten, sollten Sie ein Installationstool verwenden, um Ihre Umgebung für Sie einzurichten. virtualenv ist sehr beliebt. Wenn Sie setuptools verwenden, können Sie setup.py developden Arbeitsbaum in Ihrer aktuellen Python-Installation einfach halb installieren.

Ned Batchelder
quelle
10
Können Sie dies etwas näher erläutern? Selbst wenn Sie eine Conda / Virtualenv-Umgebung einrichten, wie würde dies das Toplevel-Verzeichnis auf Ihren Python-Pfad setzen?
compguy24
38

Ich hasse PYTHONPATH. Ich finde es spröde und ärgerlich, auf Benutzerbasis (insbesondere für Daemon-Benutzer) festzulegen und zu verfolgen, wie sich Projektordner bewegen. Ich würde viel lieber sys.pathin den Aufrufskripten für eigenständige Projekte setzen.

Dies sys.path.appendist jedoch nicht der richtige Weg. Sie können leicht Duplikate erhalten, und es werden keine .pthDateien sortiert . Besser (und besser lesbar) : site.addsitedir.

Und script.pywäre normalerweise nicht der geeignetere Ort dafür, da es sich innerhalb des Pakets befindet, das Sie auf dem Pfad verfügbar machen möchten. Bibliotheksmodule sollten sich auf keinen Fall sys.pathselbst berühren . Stattdessen haben Sie normalerweise ein Hashbanged-Skript außerhalb des Pakets, mit dem Sie die App instanziieren und ausführen. In diesem trivialen Wrapper-Skript würden Sie Bereitstellungsdetails wie sys.path-frobbing einfügen.

Bobince
quelle
16
Das Problem mit dem site.addsitedirist , dass es funktioniert appendauf sys.path, was bedeutet , dass ein installierte Paket Vorrang vor dem lokalen Paket in der Entwicklung stattfinden wird (und Haare ziehen erfolgen können). sys.path.insert(0...wird benötigt, um das zu überwinden.
Eli Bendersky
5
@EliBendersky: sollte sein sys.path.insert(1. stackoverflow.com/q/10095037/125507
Endolith
12

Im Allgemeinen würde ich das Einrichten einer Umgebungsvariablen (wie PYTHONPATH) als schlechte Praxis betrachten. Während dies für ein einmaliges Debugging in Ordnung sein mag, ist es
möglicherweise keine gute Idee , dies als reguläre Übung zu verwenden.

Die Verwendung von Umgebungsvariablen führt zu Situationen wie "es funktioniert für mich", wenn
jemand anderes Probleme in der Codebasis meldet. Dies kann auch in der Testumgebung der Fall sein, was dazu führt, dass die Tests für einen bestimmten Entwickler einwandfrei laufen, aber wahrscheinlich fehlschlagen, wenn jemand die Tests startet.

Sateesh
quelle
5

Ich denke, dass in diesem Fall die Verwendung von PYTHONPATH eine bessere Sache ist, hauptsächlich weil es keinen (fragwürdigen) unnötigen Code einführt.

Wenn Sie daran denken, braucht Ihr Benutzer das sys.pathDing schließlich nicht, weil Ihr Paket in Site-Paketen installiert wird, weil Sie ein Verpackungssystem verwenden.

Wenn der Benutzer eine "lokale Kopie" ausführt, wie Sie sie nennen, habe ich festgestellt, dass die übliche Praxis darin besteht, anzugeben, dass das Paket manuell zu PYTHONPATH hinzugefügt werden muss, wenn es außerhalb der Site-Pakete verwendet wird .

shylent
quelle
5

Zusammen mit den vielen anderen bereits erwähnten Gründen könnten Sie auch auf diese Hardcodierung hinweisen

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

ist spröde, weil es den Speicherort von script.py voraussetzt - es funktioniert nur, wenn sich script.py in Project / package befindet. Es wird unterbrochen, wenn ein Benutzer beschließt, script.py (fast) an eine andere Stelle zu verschieben / kopieren / symlink.

unutbu
quelle
2

Weder Hacking PYTHONPATHnoch sys.pathist aus den oben genannten Gründen eine gute Idee. Und um das aktuelle Projekt mit dem Site-Packages-Ordner zu verknüpfen, gibt es tatsächlich einen besseren Weg als python setup.py develop, wie hier erklärt :

pip install --editable path/to/project

Wenn Sie noch keine setup.py im Stammordner Ihres Projekts haben, ist diese gut genug, um damit zu beginnen:

from setuptools import setup
setup('project')
Peter
quelle