De onde o sys.path do Python é inicializado?

111

De onde o sys.path do Python é inicializado?

UPD : Python está adicionando alguns caminhos antes de se referir a 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']

Meu PYTHONPATH é:

    PYTHONPATH=c:\testdir

Eu me pergunto de onde vêm esses caminhos anteriores aos de PYTHONPATH?

Alex
fonte

Respostas:

77

Python realmente se esforça para definir de forma inteligente sys.path. A configuração pode ser muito complicada . O seguinte guia é um pouco incompleto guia aguado,, um pouco-errado, mas espero-útil para o programador python rank-and-file do que acontece quando figuras python para fora o que usar como os valores iniciais de sys.path, sys.executable, sys.exec_prefix, e sys.prefixem uma instalação normal do python.

Primeiro, o python dá o melhor de si para descobrir sua localização física real no sistema de arquivos com base no que o sistema operacional diz. Se o sistema operacional apenas disser que "python" está em execução, ele se encontrará em $ PATH. Ele resolve quaisquer links simbólicos. Depois de fazer isso, o caminho do executável que encontrar é usado como o valor para sys.executable, sem ifs, ands ou buts.

Em seguida, ele determina os valores iniciais para sys.exec_prefixe sys.prefix.

Se houver um arquivo chamado pyvenv.cfgno mesmo diretório sys.executableou em um diretório acima, o python o examina. Sistemas operacionais diferentes fazem coisas diferentes com este arquivo.

Um dos valores neste arquivo de configuração que o python procura é a opção de configuração home = <DIRECTORY>. O Python usará esse diretório em vez do diretório que o contém, sys.executable quando definir dinamicamente o valor inicial sys.prefixposterior. Se a applocal = trueconfiguração for exibida no pyvenv.cfgarquivo no Windows, mas não a home = <DIRECTORY>configuração, sys.prefixserá definida para o diretório que contém sys.executable.

Em seguida, a PYTHONHOMEvariável de ambiente é examinada. No Linux e Mac, sys.prefixe sys.exec_prefixsão definidos com a PYTHONHOMEvariável de ambiente, se houver, substituindo qualquer home = <DIRECTORY>configuração em pyvenv.cfg. No Windows, sys.prefixe sys.exec_prefixé definido com a PYTHONHOMEvariável de ambiente, se existir, a menos que uma home = <DIRECTORY>configuração esteja presente em pyvenv.cfg, que é usada em seu lugar.

Caso contrário, estes sys.prefixe sys.exec_prefixsão encontrados caminhando para trás a partir da localização sys.executableou do homediretório fornecido por, pyvenv.cfgse houver.

Se o arquivo lib/python<version>/dyn-loadfor encontrado nesse diretório ou em qualquer um de seus diretórios pais, esse diretório será definido como sys.exec_prefixLinux ou Mac. Se o arquivo lib/python<version>/os.pyfor encontrado no diretório ou em qualquer um de seus subdiretórios, esse diretório será definido para estar sys.prefixno Linux, Mac e Windows, com sys.exec_prefixo mesmo valor definido sys.prefixno Windows. Toda esta etapa é ignorada no Windows se applocal = trueestiver configurada. O diretório de sys.executableé usado ou, se homeestiver definido em pyvenv.cfg, será usado em vez do valor inicial de sys.prefix.

Se ele não puder encontrar esses arquivos de "referência" ou sys.prefixainda não tiver sido encontrado, o python define sys.prefixum valor de "fallback". Linux e Mac, por exemplo, usam padrões pré-compilados como os valores de sys.prefixe sys.exec_prefix. O Windows espera até que sys.pathseja totalmente descoberto para definir um valor de fallback para sys.prefix.

Então, (o que todos vocês estavam esperando), o python determina os valores iniciais que devem ser contidos sys.path.

  1. O diretório do script que o python está executando é adicionado sys.path. No Windows, é sempre a string vazia, que diz ao python para usar o caminho completo onde o script está localizado.
  2. O conteúdo da variável de ambiente PYTHONPATH, se definido, é adicionado a sys.path, a menos que você esteja no Windows e applocalesteja definido como verdadeiro em pyvenv.cfg.
  3. O caminho do arquivo zip, que está <prefix>/lib/python35.zipno Linux / Mac e os.path.join(os.dirname(sys.executable), "python.zip")no Windows, é adicionado a sys.path.
  4. Se estiver no Windows e não tiver applocal = truesido definido pyvenv.cfg, o conteúdo das subchaves da chave de registro HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\será adicionado, se houver.
  5. Se no Windows e nenhum applocal = truefoi definido pyvenv.cfge sys.prefixnão pôde ser encontrado, o conteúdo principal da chave de registro HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\é adicionado, se existir;
  6. Se estiver no Windows e não tiver applocal = truesido definido pyvenv.cfg, o conteúdo das subchaves da chave de registro HK_LOCAL_MACHINE\Software\Python\PythonCore\<DLLVersion>\PythonPath\será adicionado, se houver.
  7. Se no Windows e nenhum applocal = truefoi definido pyvenv.cfge sys.prefixnão pôde ser encontrado, o conteúdo principal da chave de registro HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\é adicionado, se existir;
  8. Se no Windows e PYTHONPATH não foi definido, o prefixo não foi encontrado, e nenhuma chave de registro estava presente, então o valor de tempo de compilação relativo de PYTHONPATH é adicionado; caso contrário, esta etapa é ignorada.
  9. Os caminhos na macro de tempo de compilação PYTHONPATH são adicionados em relação ao encontrado dinamicamente sys.prefix.
  10. No Mac e no Linux, o valor de sys.exec_prefixé adicionado. No Windows, o diretório que foi usado (ou teria sido usado) para pesquisar dinamicamente sys.prefixfoi adicionado.

Neste estágio no Windows, se nenhum prefixo for encontrado, o python tentará determiná-lo pesquisando todos os diretórios em sys.pathbusca dos arquivos de referência, como tentou fazer com o diretório sys.executableanterior, até encontrar algo. Caso contrário, sys.prefixé deixado em branco.

Finalmente, depois de tudo isso, o Python carrega o sitemódulo, que adiciona coisas ainda mais a sys.path:

Ele começa construindo até quatro diretórios de uma parte inicial e uma parte final. Para a parte da cabeça, use sys.prefixe sys.exec_prefix; cabeças vazias são ignoradas. Para a parte final, ele usa a string vazia e então lib/site-packages(no Windows) ou lib/pythonX.Y/site-packages e então lib/site-python(no Unix e Macintosh). Para cada uma das combinações head-tail distintas, ele vê se se refere a um diretório existente e, em caso afirmativo, adiciona-o a sys.path e também inspeciona o caminho recém-adicionado para arquivos de configuração.

djhaskin987
fonte
1
Apesar do que dizem seus documentos, sys.executablepode ser um link simbólico ou, na verdade, pode ser qualquer coisa se argv[0]contiver barras. O caminho real para o executável (da execv(path, argv)chamada) não é usado.
jfs
1
Com relação ao seu primeiro ponto sys.pathno Windows 10: Eu sempre obtenho o caminho completo do meu diretório de script como sys.path [0] (não cwd ''). Você deve ser capaz de executar algo comopython some\other\path\than\cwd\main.py
ford04 de
Eu concordo com @ ford04. O ponto 1 está incorreto: no Windows, o diretório do script é adicionado a sys.path, não um caminho em branco, nem cwd. Isso ocorre em várias instalações do Python 3.x.
gwideman
1
Uau, isso é incrível! Eu vi cerca de 10 outras perguntas e respostas antes de tropeçar nesta, a "verdade", mesmo que você esteja admitindo que não tem tudo.
Mike Williamson de
1
Eu acrescentaria que os arquivos relevantes site-packagestêm .pthe .egg-linksufixos.
florisla