Huevos en ruta antes de la variable de entorno PYTHONPATH

Si tengo paquetes instalados desde easy_install , los huevos se sys.path a sys.path antes de los elementos en la variable PYTHONPATH .

Por ejemplo, si tengo un paquete de egg llamado foo instalado, así como un paquete llamado foo en el directorio actual, y luego haga esto:

 PYTHONPATH="." python >>> import foo 

Esto usará la versión egg de foo lugar del directorio local. La inspección de sys.path muestra que los huevos se colocan antes de los elementos de PYTHONPATH . Esto parece roto. ¿Hay alguna manera de anular este comportamiento?

Desafortunadamente, esto se hace con una plantilla codificada dentro de setuptools/command/easy_install.py . Podría crear una herramienta de instalación parcheada con una plantilla editada, pero no he encontrado una forma clara de extender easy_install desde el exterior.

Cada vez que se ejecuta easy_install, se volverá a generar el archivo easy_install.pth . Aquí hay un script rápido que puede ejecutar después de easy_install, para eliminar el encabezado y el pie de página de easy_install.pth . Podría crear un script de shell de envoltorio para ejecutar esto inmediatamente después de easy_install :

 #!/usr/bin/env python import sys path = sys.argv[1] lines = open(path, 'rb').readlines() if lines and 'import sys' in lines[0]: open(path, 'wb').write(''.join(lines[1:-1]) + '\n') 

Ejemplo:

 % easy_install gdata % PYTHONPATH=xyz python -c 'import sys; print sys.path[:2]' ['', '/Users/pat/virt/lib/python2.6/site-packages/gdata-2.0.14-py2.6.egg'] % ./fix_path ~/virt/lib/python2.6/site-packages/easy_install.pth % PYTHONPATH=xyz python -c 'import sys; print sys.path[:2]' ['', '/Users/pat/xyz'] 

Para más aclaraciones, aquí está el formato de easy-install.pth :

 import sys; sys.__plen = len(sys.path) ./gdata-2.0.14-py2.6.egg import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new) 

Las dos líneas de import sys son las culpables de que aparezcan los huevos al comienzo del camino. Mi script simplemente elimina esas líneas sys.path -munging.

Considere utilizar la opción de línea de comandos -S para suprimir el procesamiento *.pth :

 python -c 'import sys; print("\n".join(sys.path))' python -S -c 'import sys; print("\n".join(sys.path))' 

https://docs.python.org/3/library/site.html#site.main

También puede usar -S con site.main() para retrasar el procesamiento de *.pth hasta el tiempo de ejecución, digamos para capturar el sys.path original para anexar:

 export PYTHONPATH=$( PYTHONPATH='' \ python -c 'import sys; \ sys.path.extend(sys.argv[1:]); old=list(sys.path); \ import site; site.main(); \ [ old.append(p) for p in sys.path if p not in old ]; \ sys.path=old; \ print ":".join(sys.path)' \ $EXTRA_PATH $ANOTHER_PATH) python -S ... # using explicit PYTHONPATH 
  • Comenzar desde explícito vacío PYTHONPATH
  • Añadir a sys.path explícitamente con extend
  • Importar sitio y llamar a site.main()
  • Agregue nuevas rutas a la ruta anterior y luego instálela en sys.path
  • Imprimir con “:” para PYTHONPATH
  • python -S es conveniente para ejecuciones posteriores solo usando $PYTHONPATH
  • python -S puede o no ser deseable al configurar PYTHONPATH (dependiendo de si necesita sys.path expandido antes de extender)

He hecho algo como lo siguiente para añadir a la ruta del sistema cuando ejecuto un archivo ejecutable de Python de nivel superior:

 import sys sys.path = [""] + sys.path 

A menudo, el "" para mí implica el uso del atributo __file__ para realizar una búsqueda relativa de una ruta que incluya el módulo de nivel superior para mi proyecto. Esto no se recomienda para usar en la producción de huevos, aunque parece que no me importan las consecuencias. Puede haber otra alternativa a __file__ .