Po co używać sys.path.append (path) zamiast sys.path.insert (1, path)?

88

Edycja: w oparciu o komentarz Ulfa Rompe'a, ważne jest, abyś używał „1” zamiast „0” , w przeciwnym razie zepsujesz sys.path .

Pythona zajmuję się już od jakiegoś czasu (ponad rok) i zawsze jestem zdezorientowany, dlaczego ludzie zalecają używanie sys.path.append()zamiast sys.path.insert(). Pokażę.

Powiedzmy, że pracuję nad modułem o nazwie PyWorkbooks (który jest zainstalowany na moim komputerze), ale jednocześnie pracuję nad innym modułem (powiedzmy PyJob), który zawiera PyWorkbooks. Podczas pracy nad PyJob znajduję błędy w PyWorkbooks, które poprawiam, więc chciałbym zaimportować wersję rozwojową.

Istnieje wiele sposobów pracy nad obydwoma (na przykład mógłbym umieścić mój projekt PyWorkbooks w PyJob), ale czasami nadal będę musiał bawić się ścieżką. Jednak nie mogę po prostu zrobić a sys.path.append()do folderu, w którym znajduje się PyWorkbooks . Czemu? Ponieważ python najpierw znajdzie moje zainstalowane PyWorkbooks!

Dlatego musisz wykonać sys.path.insert (1, path_to_dev_pyworkbooks)

W podsumowaniu:

sys.path.append(path_to_dev_pyworkbooks)
import PyWorkbooks # does NOT import dev pyworkbooks, imports installed one

lub:

sys.path.insert(1, path_to_dev_pyworkbooks) # based on comments you should use **1 not 0**
import PyWorkbooks # imports correct file

W przeszłości spowodowało to kilka problemów i naprawdę chciałbym, abyśmy (jako społeczność) zaczęli polecać sys.path.insert(1, path), tak jakbyś ręcznie wstawiał ścieżkę. Myślę, że można bezpiecznie powiedzieć, że jest to ścieżka, której chcesz używać!

Czy coś jest nie tak? To pytanie, które czasami mnie niepokoi i chciałem, aby było otwarte!

Garrett Berg
źródło
3
Skończyłem, sys.path.insert(1, dev_folder)ale nadal nie znajduje modułu dev i używa tylko zainstalowanego modułu. Jak to naprawić?
endolit

Odpowiedzi:

47

Jeśli masz wiele wersji pakietu / modułu, musisz używać virtualenv (moje podkreślenie):

virtualenv to narzędzie do tworzenia izolowanych środowisk Python.

Podstawowym problemem, który należy rozwiązać, są zależności i wersje, a pośrednio uprawnienia. Wyobraź sobie, że masz aplikację, która wymaga wersji 1 LibFoo, ale inna aplikacja wymaga wersji 2. Jak można używać obu tych aplikacji? Jeśli zainstalujesz wszystko w /usr/lib/python2.7/site-packages(lub w jakiejkolwiek standardowej lokalizacji twojej platformy), łatwo jest skończyć w sytuacji, w której nieumyślnie zaktualizujesz aplikację, której nie należy aktualizować.

A bardziej ogólnie, co jeśli chcesz zainstalować aplikację i zostawić ją w spokoju ? Jeśli aplikacja działa, każda zmiana w jej bibliotekach lub wersjach tych bibliotek może spowodować uszkodzenie aplikacji.

A co, jeśli nie możesz zainstalować pakietów w site-packageskatalogu globalnym ? Na przykład na współdzielonym hoście.

We wszystkich tych przypadkach virtualenvmoże ci pomóc. Tworzy środowisko, które ma własne katalogi instalacyjne, które nie współużytkuje bibliotek z innymi środowiskami virtualenv (i opcjonalnie nie ma również dostępu do bibliotek zainstalowanych globalnie).

Dlatego ludzie uważają, insert(0, że się mylą - jest to niepełne, prowizoryczne rozwiązanie problemu zarządzania wieloma środowiskami.

agf
źródło
Dzięki, niejasno wiedziałem, że coś takiego istnieje, ale do tej pory nie sprawdzałem tego. Więc to, co musiałbym z tym zrobić, to uruchomić wszystko z tłumacza w środowisku wirtualnym ... to również mogłoby działać. Dzięki!
Garrett Berg,
1
Jest to sugestia, ale nie bezpośrednio odpowiedzieć na pytanie (np mam silne powody, aby nie używać virtualenvi właściwie szukam powiązanego odpowiedzi na OP)
StephenBoesch
@javadba To może być prawda w Twoim przypadku, ale większość osób zadających to pytanie powinna używać venv.
agf
46

Jeśli naprawdę potrzebujesz użyć sys.path.insert, rozważ pozostawienie sys.path [0] takim, jakim jest:

sys.path.insert(1, path_to_dev_pyworkbooks)

Może to być ważne, ponieważ kod strony trzeciej może polegać na zgodności dokumentacji sys.path :

Zgodnie z inicjalizacją podczas uruchamiania programu, pierwsza pozycja na tej liście, ścieżka [0], jest katalogiem zawierającym skrypt, który został użyty do wywołania interpretera Pythona.

Ulf Rompe
źródło
13

mylisz koncepcję dołączania i poprzedzania. następujący kod jest w trakcie:

sys.path.insert(1,'/thePathToYourFolder/')

umieszcza nowe informacje na początku (dobrze, po drugie, żeby być precyzyjnym) sekwencji wyszukiwania, przez którą przejdzie twój interpreter. sys.path.append()umieszcza rzeczy na samym końcu sekwencji wyszukiwania.

wskazane jest, abyś używał czegoś takiego virtualenvzamiast ręcznego kodowania katalogów z pakietami za PYTHONPATHkażdym razem. aby skonfigurować różne ekosystemy oddzielające pakiety witryn i możliwe wersje Pythona, przeczytaj te dwa blogi:

  1. wprowadzenie do ekosystemów Pythona

  2. ładowanie środowisk wirtualnych Pythona

jeśli zdecydujesz się pójść ścieżką do izolacji środowiska, z pewnością skorzystasz na przejrzeniu virtualenvwrapper: http://www.doughellmann.com/docs/virtualenvwrapper/

samkhan13
źródło
1
Linki „Python ecosystems Introduction”, „bootstrapping python virtual environment” zostały wycofane. Prosimy o rozważenie ich rewitalizacji.
Pradeep Singh