¿Por qué utilizar sys.path.append (ruta) en lugar de sys.path.insert (1, ruta)?

88

Editar: basado en un comentario de Ulf Rompe, es importante que use "1" en lugar de "0" , de lo contrario romperá sys.path .

He estado haciendo Python durante bastante tiempo (más de un año), y siempre me confunde por qué la gente recomienda que use en sys.path.append()lugar de sys.path.insert(). Déjame demostrarte.

Digamos que estoy trabajando en un módulo llamado PyWorkbooks (que está instalado en mi computadora), pero estoy trabajando simultáneamente en un módulo diferente (digamos PyJob) que incorpora PyWorkbooks. Mientras trabajo en PyJob, encuentro errores en PyWorkbooks que estoy corrigiendo, así que me gustaría importar una versión de desarrollo.

Hay varias formas de trabajar en ambos (podría poner mi proyecto PyWorkbooks dentro de PyJob, por ejemplo), pero a veces todavía necesitaré jugar con la ruta. Sin embargo, no puedo simplemente hacer una sys.path.append()en la carpeta donde se encuentra PyWorkbooks . ¿Por qué? ¡Porque python encontrará primero mis PyWorkbooks instalados!

Es por eso que tienes que hacer un sys.path.insert (1, path_to_dev_pyworkbooks)

En resumen:

sys.path.append(path_to_dev_pyworkbooks)
import PyWorkbooks # does NOT import dev pyworkbooks, imports installed one

o:

sys.path.insert(1, path_to_dev_pyworkbooks) # based on comments you should use **1 not 0**
import PyWorkbooks # imports correct file

Esto me ha causado algunos problemas en el pasado, y realmente me gustaría que nosotros (como comunidad) comenzáramos a recomendar sys.path.insert(1, path), como si estuviera insertando manualmente una ruta, creo que es seguro decir que esa es la ruta que desea ¡usar!

¿O tengo algo mal? Es una pregunta que a veces me molesta y ¡la quería al descubierto!

Garrett Berg
fuente
3
Lo he hecho, sys.path.insert(1, dev_folder)pero todavía no encuentro el módulo de desarrollo y solo estoy usando el módulo instalado. ¿Cómo puedo solucionar esto?
endolito

Respuestas:

47

Si tiene varias versiones de un paquete / módulo, debe usar virtualenv (el énfasis es mío):

virtualenv es una herramienta para crear entornos Python aislados.

El problema básico que se está abordando es uno de dependencias y versiones, e indirectamente permisos. Imagine que tiene una aplicación que necesita la versión 1 de LibFoo, pero otra aplicación requiere la versión 2. ¿Cómo puede utilizar ambas aplicaciones? Si instala todo en /usr/lib/python2.7/site-packages(o cualquiera que sea la ubicación estándar de su plataforma), es fácil terminar en una situación en la que involuntariamente actualice una aplicación que no debería actualizarse.

O de manera más general, ¿qué pasa si desea instalar una aplicación y dejarla así ? Si una aplicación funciona, cualquier cambio en sus bibliotecas o en las versiones de esas bibliotecas puede dañar la aplicación.

Además, ¿qué pasa si no puede instalar paquetes en el site-packagesdirectorio global ? Por ejemplo, en un host compartido.

En todos estos casos, te virtualenvpuede ayudar. Crea un entorno que tiene sus propios directorios de instalación, que no comparte bibliotecas con otros entornos virtualenv (y, opcionalmente, tampoco accede a las bibliotecas instaladas globalmente).

Es por eso que la gente considera insert(0, que está equivocada: es una solución provisional incompleta al problema de administrar múltiples entornos.

agf
fuente
Gracias, sabía vagamente que existía algo como esto, pero en realidad no lo he comprobado hasta ahora. Entonces, lo que tendría que hacer con esto es ejecutar todo, desde el intérprete en el entorno virtual ... que también podría funcionar. ¡Gracias!
Garrett Berg
1
Esta es una sugerencia pero no responde directamente a la pregunta (por ejemplo, tengo fuertes razones para no usar virtualenvy de hecho estoy buscando la respuesta asociada al OP)
StephenBoesch
@javadba Eso puede ser cierto para su caso, pero la mayoría de las personas que hacen esta pregunta deberían usar venv.
agf
46

Si realmente necesita usar sys.path.insert, considere dejar sys.path [0] tal como está:

sys.path.insert(1, path_to_dev_pyworkbooks)

Esto podría ser importante ya que el código de terceros puede depender de la conformidad de la documentación de sys.path :

Como se inicializó al iniciar el programa, el primer elemento de esta lista, la ruta [0], es el directorio que contiene el script que se utilizó para invocar al intérprete de Python.

Ulf Rompe
fuente
13

está confundiendo el concepto de añadir y anteponer. antecede el siguiente código:

sys.path.insert(1,'/thePathToYourFolder/')

coloca la nueva información al principio (bueno, segundo, para ser precisos) de la secuencia de búsqueda por la que pasará su intérprete. sys.path.append()pone las cosas al final de la secuencia de búsqueda.

es aconsejable que use algo como en virtualenvlugar de codificar manualmente los directorios de su paquete en el PYTHONPATHarchivo everytime. Para configurar varios ecosistemas que separan los paquetes de su sitio y las posibles versiones de Python, lea estos dos blogs:

  1. introducción a los ecosistemas de pitón

  2. arrancando entornos virtuales de Python

si decide avanzar por el camino hacia el aislamiento del entorno, sin duda se beneficiaría al buscar virtualenvwrapper: http://www.doughellmann.com/docs/virtualenvwrapper/

samkhan13
fuente
1
Se han retirado los enlaces "introducción a los ecosistemas de Python", "arrancando entornos virtuales de Python". Por favor, considere revitalizarlos.
Pradeep Singh