web-dev-qa-db-fra.com

PYTHONPATH contre sys.path

Un autre développeur et moi ne sommes pas d'accord pour savoir si PYTHONPATH ou sys.path doit être utilisé pour permettre à Python de trouver un Python package dans un répertoire utilisateur (par exemple, développement)) .

Nous avons un projet Python avec une structure de répertoire typique:

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

Dans script.py, nous devons faire import package.lib. Lorsque le package est installé dans site-packages, script.py peut trouver package.lib.

Lorsque vous travaillez à partir d'un répertoire utilisateur, cependant, quelque chose d'autre doit être fait. Ma solution est de configurer mon PYTHONPATH pour inclure "~/Project". Un autre développeur veut mettre cette ligne de code au début de script.py:

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

Pour que Python puisse trouver la copie locale de package.lib.

Je pense que c'est une mauvaise idée, car cette ligne n'est utile que pour les développeurs ou les personnes qui s'exécutent à partir d'une copie locale, mais je ne peux pas donner une bonne raison pour laquelle c'est une mauvaise idée.

Faut-il utiliser PYTOHNPATH, sys.path, ou est-ce bien?

76
gaefan

Si la seule raison de modifier le chemin est pour les développeurs travaillant à partir de leur arborescence de travail, vous devez utiliser un outil d'installation pour configurer votre environnement pour vous. virtualenv est très populaire, et si vous utilisez setuptools, vous pouvez simplement exécuter setup.py develop pour semi-installer l'arborescence de travail dans votre installation actuelle Python.

42
Ned Batchelder

Je déteste PYTHONPATH. Je trouve qu'il est fragile et ennuyeux de définir une configuration par utilisateur (en particulier pour les utilisateurs de démons) et de suivre le mouvement des dossiers de projet. Je préfère de loin définir sys.path dans les scripts d'appel pour les projets autonomes.

Toutefois sys.path.append n'est pas la façon de le faire. Vous pouvez facilement obtenir des doublons et cela ne trie pas .pth des dossiers. Mieux (et plus lisible): site.addsitedir.

Et script.py ne serait normalement pas l'endroit le plus approprié pour le faire, car c'est à l'intérieur le paquet que vous voulez rendre disponible sur le chemin. Les modules de bibliothèque ne doivent certainement pas toucher sys.path eux-mêmes. Au lieu de cela, vous auriez normalement un script hashbanged en dehors du package que vous utilisez pour instancier et exécuter l'application, et c'est dans ce script wrapper trivial que vous mettriez des détails de déploiement comme sys.path- frobbing.

34
bobince

En général, je considérerais la mise en place d'une variable d'environnement (comme PYTHONPATH) comme une mauvaise pratique. Bien que cela puisse être bien pour un débogage ponctuel, mais en l'utilisant comme
une pratique régulière pourrait ne pas être une bonne idée.

L'utilisation de la variable d'environnement conduit à des situations comme "ça marche pour moi" lorsque quelqu'un
sinon signale des problèmes dans la base de code. On peut également appliquer la même pratique avec l'environnement de test, ce qui conduit à des situations comme les tests qui fonctionnent correctement pour un développeur particulier, mais échouent probablement lorsque quelqu'un lance les tests.

10
sateesh

Avec les nombreuses autres raisons déjà mentionnées, vous pouvez également souligner que le codage en dur

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

est fragile car il suppose l'emplacement de script.py - cela ne fonctionnera que si script.py se trouve dans Project/package. Il se cassera si un utilisateur décide de déplacer/copier/lien symbolique script.py (presque) n'importe où ailleurs.

5
unutbu

Je pense que dans ce cas, utiliser PYTHONPATH est une meilleure chose, principalement parce qu'il n'introduit pas de code inutile (discutable).

Après tout, si vous y pensez, votre tilisateur n'a pas besoin de cela sys.path chose, parce que votre paquet sera installé dans les sites-packages, parce que vous utiliserez un système d'emballage.

Si l'utilisateur choisit de s'exécuter à partir d'une "copie locale", comme vous l'appelez, j'ai observé que la pratique habituelle est de déclarer que le package doit être ajouté manuellement à PYTHONPATH, s'il est utilisé en dehors des sites-packages .

4
shylent