Skąd jest inicjalizowany plik sys.path języka Python?

111

Skąd jest inicjalizowany plik sys.path języka Python?

UPD : Python dodaje kilka ścieżek przed odwołaniem się do PYTHONPATH:

    >>> import sys
    >>> from pprint import pprint as p
    >>> p(sys.path)
    ['',
     'C:\\Python25\\lib\\site-packages\\setuptools-0.6c9-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\orbited-0.7.8-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\morbid-0.8.6.1-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\demjson-1.4-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\stomper-0.2.2-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\uuid-1.30-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\stompservice-0.1.0-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\cherrypy-3.0.1-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\pyorbited-0.2.2-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\flup-1.0.1-py2.5.egg',
     'C:\\Python25\\lib\\site-packages\\wsgilog-0.1-py2.5.egg',
     'c:\\testdir',
     'C:\\Windows\\system32\\python25.zip',
     'C:\\Python25\\DLLs',
     'C:\\Python25\\lib',
     'C:\\Python25\\lib\\plat-win',
     'C:\\Python25\\lib\\lib-tk',
     'C:\\Python25',
     'C:\\Python25\\lib\\site-packages',
     'C:\\Python25\\lib\\site-packages\\PIL',
     'C:\\Python25\\lib\\site-packages\\win32',
     'C:\\Python25\\lib\\site-packages\\win32\\lib',
     'C:\\Python25\\lib\\site-packages\\Pythonwin']

Moja PYTHONPATH to:

    PYTHONPATH=c:\testdir

Zastanawiam się, skąd pochodzą te ścieżki przed PYTHONPATH?

Alex
źródło

Odpowiedzi:

77

Python naprawdę bardzo się stara, aby inteligentnie ustawić sys.path. Sposób ustawienia może być naprawdę skomplikowany . Poniższy przewodnik jest okrojoną, nieco-niekompletny, nieco-źle, ale mam nadzieję, użyteczny przewodnik dla szeregowych plik python programisty, co się dzieje, gdy dane python, co do wykorzystania jako wartości początkowych o sys.path, sys.executable, sys.exec_prefix, i sys.prefixw normalnej instalacji Pythona.

Po pierwsze, python robi wszystko, co w jego mocy, aby ustalić rzeczywistą fizyczną lokalizację w systemie plików na podstawie tego, co powie mu system operacyjny. Jeśli system operacyjny mówi tylko, że „python” jest uruchomiony, znajduje się w $ PATH. Rozwiązuje wszelkie dowiązania symboliczne. Gdy to zrobi, ścieżka do znalezionego pliku wykonywalnego jest używana jako wartość for sys.executable, no ifs, ands lub buts.

Następnie określa początkowe wartości dla sys.exec_prefixi sys.prefix.

Jeśli istnieje plik wywołany pyvenv.cfgw tym samym katalogu co sys.executablelub o jeden wyżej, Python go przegląda. Różne systemy operacyjne robią różne rzeczy z tym plikiem.

Jedną z wartości w tym pliku konfiguracyjnym, której szuka Python, jest opcja konfiguracji home = <DIRECTORY>. Python użyje tego katalogu zamiast katalogu zawierającego, sys.executable gdy dynamicznie ustawi początkową wartość sys.prefixpóźniej. Jeśli applocal = trueustawienie pojawia się w pyvenv.cfgpliku w systemie Windows, ale nie jest to home = <DIRECTORY>ustawienie, sys.prefixzostanie ustawione na katalog zawierający sys.executable.

Następnie PYTHONHOMEsprawdzana jest zmienna środowiskowa. W systemach Linux i Mac sys.prefixi sys.exec_prefixsą ustawione na PYTHONHOMEzmienną środowiskową, jeśli istnieje, zastępując wszelkie home = <DIRECTORY>ustawienia w pyvenv.cfg. W systemie Windows sys.prefixi sys.exec_prefixjest ustawiony w PYTHONHOMEzmiennej środowiskowej, jeśli istnieje, chybahome = <DIRECTORY> ustawienie jest obecny w pyvenv.cfg, który jest używany zamiast.

W przeciwnym razie te sys.prefixi sys.exec_prefixmożna znaleźć, przechodząc wstecz od lokalizacji sys.executablelub homekatalogu podanego przez, pyvenv.cfgjeśli istnieje.

Jeśli plik lib/python<version>/dyn-loadzostanie znaleziony w tym katalogu lub w dowolnym z jego katalogów nadrzędnych, będzie to katalog sys.exec_prefixw systemie Linux lub Mac. Jeśli plik lib/python<version>/os.pyzostanie znaleziony w katalogu lub w dowolnym z jego podkatalogów, ten katalog jest ustawiony sys.prefixna system Linux, Mac i Windows, z sys.exec_prefixustawioną taką samą wartością jak sys.prefixw systemie Windows. Cały ten krok jest pomijany w systemie Windows, jeśli applocal = truejest ustawiony. sys.executableUżywany jest katalog of lub, jeśli homejest ustawiony w pyvenv.cfg, używany jest zamiast niego jako wartość początkowa sys.prefix.

Jeśli nie może znaleźć tych plików „punktów orientacyjnych” lub sys.prefixnie został jeszcze znaleziony, wówczas Python ustawia sys.prefixwartość „rezerwową”. Na przykład Linux i Mac używają wstępnie skompilowanych wartości domyślnych jako wartości sys.prefixi sys.exec_prefix. System Windows czeka, aż sys.pathzostanie w pełni skonfigurowany, aby ustawić wartość rezerwową dla sys.prefix.

Następnie (na co wszyscy czekaliście) python określa początkowe wartości, które mają być zawarte sys.path.

  1. Katalog skryptu, który wykonuje python, jest dodawany do sys.path. W systemie Windows jest to zawsze pusty ciąg, który mówi Pythonowi, aby zamiast tego używał pełnej ścieżki, w której znajduje się skrypt.
  2. Zawartość zmiennej środowiskowej PYTHONPATH, jeśli jest ustawiona, jest dodawana do sys.path, chyba że jesteś w systemie Windows i applocaljest ustawiona na true w pyvenv.cfg.
  3. Ścieżka do pliku zip, która znajduje się <prefix>/lib/python35.zipw systemie Linux / Mac i os.path.join(os.dirname(sys.executable), "python.zip")Windows, jest dodawana do sys.path.
  4. Jeśli w systemie Windows applocal = trueustawiono nie pyvenv.cfg, zawartość podkluczy klucza rejestru HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\jest dodawana, jeśli istnieje.
  5. Jeśli w systemie Windows i nie applocal = truezostał ustawiony w pyvenv.cfg, i sys.prefixnie można znaleźć, wówczas zawartość podstawowych Spośród klucza rejestru HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\dodaje, jeśli istnieje;
  6. Jeśli w systemie Windows applocal = trueustawiono nie pyvenv.cfg, zawartość podkluczy klucza rejestru HK_LOCAL_MACHINE\Software\Python\PythonCore\<DLLVersion>\PythonPath\jest dodawana, jeśli istnieje.
  7. Jeśli w systemie Windows i nie applocal = truezostał ustawiony w pyvenv.cfg, i sys.prefixnie można znaleźć, wówczas zawartość podstawowych Spośród klucza rejestru HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\dodaje, jeśli istnieje;
  8. Jeśli w systemie Windows i PYTHONPATH nie zostało ustawione, przedrostek nie został znaleziony i nie było żadnych kluczy rejestru, to dodawana jest względna wartość czasu kompilacji PYTHONPATH; w przeciwnym razie ten krok jest ignorowany.
  9. Ścieżki w makrze PYTHONPATH używanym w czasie kompilacji są dodawane względem pliku znalezionego dynamicznie sys.prefix.
  10. W systemach Mac i Linux wartość sys.exec_prefixdodana. W systemie Windows sys.prefixdodawany jest katalog, który był używany (lub byłby używany) do wyszukiwania dynamicznego .

Na tym etapie w systemie Windows, jeśli nie zostanie znaleziony żaden prefiks, python spróbuje go określić, przeszukując wszystkie katalogi w sys.pathposzukiwaniu plików punktów orientacyjnych, tak jak próbował zrobić z wcześniejszym katalogiem sys.executable, aż coś znajdzie. Jeśli tak nie sys.prefixjest, pozostaje puste.

Wreszcie, po tym wszystkim, Python ładuje sitemoduł, który dodaje jeszcze więcej rzeczy do sys.path:

Rozpoczyna się od skonstruowania do czterech katalogów z części głównej i części końcowej. W części głowy używa sys.prefixi sys.exec_prefix; puste głowy są pomijane. W części końcowej używa pustego ciągu, a następnie lib/site-packages(w systemie Windows) lub lib/pythonX.Y/site-packages i następnie lib/site-python(w systemach Unix i Macintosh). Dla każdej z różnych kombinacji head-tail sprawdza, czy odwołuje się do istniejącego katalogu, a jeśli tak, dodaje go do sys.path, a także sprawdza nowo dodaną ścieżkę w poszukiwaniu plików konfiguracyjnych.

djhaskin987
źródło
1
Pomimo tego, co mówią jego dokumenty, sys.executablemoże to być dowiązanie symboliczne lub w rzeczywistości może to być wszystko, jeśli argv[0]zawiera ukośniki. Rzeczywista ścieżka do pliku wykonywalnego (z execv(path, argv)wywołania) nie jest używana.
jfs
1
Jeśli chodzi o Twój pierwszy punkt sys.pathdotyczący systemu Windows 10: zawsze otrzymuję pełną ścieżkę katalogu skryptów jako sys.path [0] (nie cwd ''). Powinieneś być w stanie wykonać coś takiegopython some\other\path\than\cwd\main.py
ford04
Zgadzam się z @ ford04. Punkt 1 jest nieprawidłowy: w systemie Windows katalog skryptu jest dodawany do sys.path, a nie pusta ścieżka ani cwd. To jest w różnych instalacjach Pythona 3.x.
gwideman
1
Wow, to jest niesamowite! Widziałem około 10 innych pytań i odpowiedzi, zanim natknąłem się na tę „prawdę”, mimo że upokarzasz się przyznając, że nie masz wszystkiego.
Mike Williamson
1
Dodam, że odpowiednie pliki site-packagesmają .pthi .egg-linkprzyrostki.
florisla