PYTHONPATH vs. sys.path


92

Outro desenvolvedor e eu discordamos sobre se PYTHONPATH ou sys.path devem ser usados ​​para permitir que Python encontre um pacote Python em um diretório de usuário (por exemplo, desenvolvimento).

Temos um projeto Python com uma estrutura de diretório típica:

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

Em script.py, precisamos fazer import package.lib. Quando o pacote é instalado em sites-packages, script.py pode encontrar package.lib.

Ao trabalhar a partir de um diretório de usuário, entretanto, algo mais precisa ser feito. Minha solução é definir meu PYTHONPATH para incluir "~ / Projeto". Outro desenvolvedor deseja colocar esta linha de código no início de script.py:

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

Para que Python possa encontrar a cópia local de package.lib.

Acho que é uma má ideia, já que esta linha só é útil para desenvolvedores ou pessoas que executam uma cópia local, mas não posso dar uma boa razão para que seja uma má ideia.

Devemos usar PYTOHNPATH, sys.path ou tudo bem?


4
Parece que os votos e as respostas estão divididos de maneira bastante uniforme, com uma leve tendência ao uso de PYTHON_PATH, embora isso possa ser uma amostragem de ruído ou distorção não intencional da pergunta.
AJP

Respostas:


42

Se o único motivo para modificar o caminho for para desenvolvedores trabalhando em sua árvore de trabalho, você deve usar uma ferramenta de instalação para configurar seu ambiente para você. virtualenv é muito popular, e se você estiver usando ferramentas de instalação, você pode simplesmente executar setup.py developpara semi-instalar a árvore de trabalho em sua instalação atual do Python.


10
Você pode oferecer um pouco mais de esclarecimento sobre isso? Mesmo se você criar um ambiente conda / virtualenv, como isso colocaria o diretório de nível superior em seu caminho python?
compguy24 de

38

Eu odeio PYTHONPATH. Acho frágil e irritante definir por usuário (especialmente para usuários de daemon) e acompanhar conforme as pastas do projeto se movem. Eu preferiria definirsys.path nos scripts invoke para projetos autônomos.

No entanto, sys.path.appendnão é a maneira de fazer isso. Você pode obter facilmente duplicatas e não classifica os .ptharquivos. Melhor (e mais legível): site.addsitedir.

E script.pynormalmente não seria o lugar mais apropriado para fazer isso, pois está dentro do pacote que você deseja disponibilizar no caminho. Módulos de biblioteca certamente não devem se tocar sys.path. Em vez disso, você normalmente teria um script hashbanged fora do pacote que você usa para instanciar e executar o aplicativo, e é nesse script de wrapper trivial que você colocaria detalhes de implantação como sys.path-frobbing.


16
O problema site.addsitediré que ele faz um appendon sys.path, o que significa que um pacote instalado terá precedência sobre o pacote local em desenvolvimento (e isso pode causar uma confusão). sys.path.insert(0...é necessário para superar isso.
Eli Bendersky

5
@EliBendersky: deveria ser sys.path.insert(1. stackoverflow.com/q/10095037/125507
endolith

12

Em geral, eu consideraria a configuração de uma variável de ambiente (como PYTHONPATH) uma prática ruim. Embora isso possa ser bom para uma depuração isolada, usar isso como
uma prática regular pode não ser uma boa ideia.

O uso da variável de ambiente leva a situações como "funciona para mim", quando outra
pessoa relata problemas na base de código. Além disso, pode-se realizar a mesma prática com o ambiente de teste, levando a situações como a execução de testes bem para um desenvolvedor em particular, mas provavelmente falhando quando alguém os inicia.


5

Eu acho que, neste caso, usar PYTHONPATH é uma coisa melhor, principalmente porque ele não introduz código desnecessário (questionável).

Afinal, se você pensar bem, seu usuário não precisa disso sys.path, porque seu pacote será instalado em sites-packages, porque você estará usando um sistema de empacotamento.

Se o usuário escolher executar a partir de uma "cópia local", como você a chama, observei que a prática usual é afirmar que o pacote precisa ser adicionado a PYTHONPATH manualmente, se usado fora dos pacotes do site .


5

Junto com os muitos outros motivos já mencionados, você também pode apontar que a codificação permanente

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

é frágil porque presume a localização de script.py - só funcionará se script.py estiver localizado em Projeto / pacote. Ele será interrompido se um usuário decidir mover / copiar / symlink script.py (quase) para qualquer outro lugar.


2

Nem hackear PYTHONPATHnem sys.pathé uma boa ideia pelos motivos mencionados. E para vincular o projeto atual à pasta de pacotes do site, há realmente uma maneira melhor do que python setup.py develop, conforme explicado aqui :

pip install --editable path/to/project

Se você ainda não tem um setup.py na pasta raiz do seu projeto, este é bom o suficiente para começar:

from setuptools import setup
setup('project')
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.