PYTHONPATH kontra sys.path

93

Inny programista i ja nie zgadzamy się co do tego, czy PYTHONPATH lub sys.path powinny być używane, aby umożliwić Pythonowi znalezienie pakietu Pythona w katalogu użytkownika (np. Deweloperskim).

Mamy projekt w Pythonie z typową strukturą katalogów:

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

W script.py musimy to zrobić import package.lib. Gdy pakiet jest instalowany w pakietach witryn, plik script.py może znaleźć package.lib.

Jednak podczas pracy z katalogu użytkownika należy zrobić coś innego. Moim rozwiązaniem jest ustawienie mojej PYTHONPATH tak, aby zawierała „~ / Project”. Inny programista chce umieścić tę linię kodu na początku script.py:

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

Aby Python mógł znaleźć lokalną kopię package.lib.

Myślę, że to zły pomysł, ponieważ ta linia jest przydatna tylko dla programistów lub osób korzystających z lokalnej kopii, ale nie mogę podać dobrego powodu, dla którego jest to zły pomysł.

Czy powinniśmy użyć PYTOHNPATH, sys.path, czy też jest w porządku?

gaefan
źródło
4
Wygląda na to, że głosy i odpowiedzi są podzielone dość równomiernie, z niewielkim naciskiem na użycie PYTHON_PATH, chociaż może to być próbkowanie szumu lub niezamierzonego odchylenia od pytania.
AJP
Aby zobaczyć różnicę między PATHi sys.path(i pośrednio PYTHONPATH), zobacz także stackoverflow.com/questions/25344841/sys-path-vs-path
tripleee

Odpowiedzi:

42

Jeśli jedynym powodem modyfikacji ścieżki są programiści pracujący w ich drzewie roboczym, powinieneś użyć narzędzia instalacyjnego, aby skonfigurować swoje środowisko. virtualenv jest bardzo popularny, a jeśli używasz setuptools, możesz po prostu uruchomić, setup.py developaby częściowo zainstalować drzewo robocze w bieżącej instalacji Pythona.

Ned Batchelder
źródło
11
Czy możesz podać trochę więcej wyjaśnień w tej sprawie? Nawet jeśli stworzysz środowisko conda / virtualenv, w jaki sposób umieściłoby to katalog najwyższego poziomu na ścieżce do Pythona?
compguy24
38

Nienawidzę PYTHONPATH. Uważam, że ustawienie dla każdego użytkownika (szczególnie dla użytkowników demonów) i śledzenie przemieszczania się folderów projektów jest kruche i denerwujące. Wolałbym raczej ustawić sys.pathw skryptach wywołania dla samodzielnych projektów.

Jednak sys.path.appendnie jest to sposób na zrobienie tego. Możesz łatwo uzyskać duplikaty i nie sortuje .pthplików. Lepiej (i bardziej czytelny) site.addsitedir.

I script.pynormalnie nie byłoby bardziej odpowiednim miejscem do zrobienia tego, ponieważ znajduje się w pakiecie, który chcesz udostępnić na ścieżce. Moduły biblioteczne z pewnością nie powinny się dotykać sys.path. Zamiast tego normalnie miałbyś skrypt hashbanged poza pakietem, którego używasz do tworzenia wystąpienia i uruchamiania aplikacji, i to w tym trywialnym skrypcie opakowującym umieszczasz szczegóły wdrożenia, takie jak sys.path-frobbing.

bobince
źródło
17
Problem site.addsitedirpolega na tym, że działa appendon sys.path, co oznacza, że ​​zainstalowany pakiet będzie miał pierwszeństwo przed pakietem lokalnym w trakcie opracowywania (i może dojść do wyrywania włosów). sys.path.insert(0...trzeba to przezwyciężyć.
Eli Bendersky
5
@EliBendersky: powinno być sys.path.insert(1. stackoverflow.com/q/10095037/125507
endolith
12

Ogólnie uważam, że ustawienie zmiennej środowiskowej (takiej jak PYTHONPATH) jest złą praktyką. Chociaż może to być w porządku w przypadku jednorazowego debugowania, ale używanie tego jako
zwykłej praktyki może nie być dobrym pomysłem.

Użycie zmiennej środowiskowej prowadzi do sytuacji typu „u mnie działa”, gdy ktoś
inny zgłasza problemy w kodzie. Można również przeprowadzić tę samą praktykę w środowisku testowym, co prowadzi do sytuacji, takich jak testy, które działają dobrze dla określonego programisty, ale prawdopodobnie kończą się niepowodzeniem, gdy ktoś uruchamia testy.

sateesh
źródło
6

Oprócz wielu innych powodów, o których już wspomniano, możesz również wskazać na to twarde kodowanie

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

jest kruchy, ponieważ zakłada lokalizację script.py - będzie działać tylko wtedy, gdy skrypt.py znajduje się w projekcie / pakiecie. Zepsuje się, jeśli użytkownik zdecyduje się przenieść / skopiować / dowiązanie symboliczne script.py (prawie) gdziekolwiek indziej.

unutbu
źródło
5

Myślę, że w tym przypadku użycie PYTHONPATH jest lepsze, głównie dlatego, że nie wprowadza (wątpliwego) niepotrzebnego kodu.

W końcu, jeśli o tym pomyślisz, twój użytkownik tego nie potrzebujesys.path , ponieważ twój pakiet zostanie zainstalowany w pakietach lokacji, ponieważ będziesz używać systemu pakowania.

Jeśli użytkownik wybierze uruchomienie z "kopii lokalnej", jak to nazywasz, to zauważyłem, że zwykłą praktyką jest stwierdzenie, że pakiet musi być dodany ręcznie do PYTHONPATH, jeśli jest używany poza pakietami witryny .

shylent
źródło
3

Ani hakowanie, PYTHONPATHani nie sys.pathjest dobrym pomysłem z wyżej wymienionych powodów. A do łączenia bieżącego projektu z folderem pakietów witryn jest właściwie lepszy sposób niż python setup.py develop, jak wyjaśniono tutaj :

pip install --editable path/to/project

Jeśli nie masz jeszcze pliku setup.py w folderze głównym swojego projektu, ten jest wystarczająco dobry, aby zacząć od:

from setuptools import setup
setup('project')
Piotr
źródło