PYTHONPATH frente a sys.path

93

Otro desarrollador y yo no estamos de acuerdo sobre si PYTHONPATH o sys.path deben usarse para permitir que Python encuentre un paquete de Python en un directorio de usuario (por ejemplo, desarrollo).

Tenemos un proyecto de Python con una estructura de directorios típica:

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

En script.py, tenemos que hacer import package.lib. Cuando el paquete está instalado en site-packages, script.py puede encontrar package.lib.

Sin embargo, cuando se trabaja desde un directorio de usuario, es necesario hacer algo más. Mi solución es configurar mi PYTHONPATH para incluir "~ / Proyecto". Otro desarrollador quiere poner esta línea de código al principio de script.py:

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

Para que Python pueda encontrar la copia local de package.lib.

Creo que es una mala idea, ya que esta línea solo es útil para desarrolladores o personas que ejecutan desde una copia local, pero no puedo dar una buena razón por la que es una mala idea.

¿Debemos usar PYTOHNPATH, sys.path o bien?

gaefan
fuente
4
Parece que los votos y las respuestas se dividen de manera bastante uniforme con una ligera inclinación hacia el uso de PYTHON_PATH, aunque esto podría ser ruido de muestreo o sesgo involuntario de la pregunta.
AJP
Para conocer la diferencia entre PATHy sys.path(e indirectamente PYTHONPATH), consulte también stackoverflow.com/questions/25344841/sys-path-vs-path
tripleee

Respuestas:

42

Si la única razón para modificar la ruta es que los desarrolladores trabajen desde su árbol de trabajo, entonces debería usar una herramienta de instalación para configurar su entorno por usted. virtualenv es muy popular, y si está usando setuptools, simplemente puede ejecutar setup.py developpara semi-instalar el árbol de trabajo en su instalación actual de Python.

Ned Batchelder
fuente
11
¿Puede ofrecer un poco más de aclaración sobre esto? Incluso si se coloca en un entorno conda / virtualenv, ¿cómo pondría esto el directorio de nivel superior en su ruta de Python?
compguy24
38

Odio PYTHONPATH. Me resulta frágil y molesto configurarlo por usuario (especialmente para los usuarios de demonios) y realizar un seguimiento de cómo se mueven las carpetas del proyecto. Preferiría establecer sys.pathlos scripts de invocación para proyectos independientes.

Sin embargo, sys.path.appendno es la forma de hacerlo. Puede obtener duplicados fácilmente y no clasifica los .ptharchivos. Mejor (y más legible): site.addsitedir.

Y script.pynormalmente no sería el lugar más apropiado para hacerlo, ya que está dentro del paquete que desea que esté disponible en la ruta. Los módulos de la biblioteca ciertamente no deberían tocarse a sys.pathsí mismos. En su lugar, normalmente tendría un script hashbanged fuera del paquete que usa para crear una instancia y ejecutar la aplicación, y en este script contenedor trivial sys.pathcolocaría detalles de implementación como -frobbing.

bobince
fuente
17
El problema site.addsitedires que lo hace un appendsobre sys.path, lo que significa que un paquete instalado tendrá prioridad sobre el paquete local en el desarrollo (y tirar del pelo puede sobrevenir). sys.path.insert(0...es necesario para superar eso.
Eli Bendersky
5
@EliBendersky: debería ser sys.path.insert(1. stackoverflow.com/q/10095037/125507
endolito
12

En general, consideraría que configurar una variable de entorno (como PYTHONPATH) es una mala práctica. Si bien esto puede estar bien para una depuración única, usar esto como
una práctica regular puede no ser una buena idea.

El uso de la variable de entorno conduce a situaciones como "funciona para mí" cuando alguien
más informa problemas en la base del código. También se puede llevar a cabo la misma práctica con el entorno de prueba, lo que lleva a situaciones como las pruebas que funcionan bien para un desarrollador en particular, pero probablemente fallan cuando alguien lanza las pruebas.

sateesh
fuente
6

Junto con las muchas otras razones ya mencionadas, también podría señalar que la codificación

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

es frágil porque asume la ubicación de script.py; solo funcionará si script.py se encuentra en Project / package. Se romperá si un usuario decide mover / copiar / enlace simbólico script.py (casi) a cualquier otro lugar.

unutbu
fuente
5

Creo que, en este caso, usar PYTHONPATH es algo mejor, principalmente porque no introduce código innecesario (cuestionable).

Después de todo, si lo piensa, su usuario no necesita eso sys.path, porque su paquete se instalará en los paquetes del sitio, porque estará usando un sistema de empaquetado.

Si el usuario elige ejecutar desde una "copia local", como usted lo llama, entonces he observado que la práctica habitual es indicar que el paquete debe agregarse a PYTHONPATH manualmente, si se usa fuera de los paquetes del sitio. .

shylent
fuente
3

Ni piratear PYTHONPATHni sys.pathes una buena idea debido a las razones antes mencionadas. Y para vincular el proyecto actual a la carpeta de paquetes del sitio, en realidad hay una manera mejor que python setup.py develop, como se explica aquí :

pip install --editable path/to/project

Si aún no tiene un setup.py en la carpeta raíz de su proyecto, este es lo suficientemente bueno para comenzar con:

from setuptools import setup
setup('project')
Pedro
fuente