Llamar automáticamente el código de inicialización común sin crear el archivo __init__.py

Tengo dos directorios en mi proyecto:

project/ src/ scripts/ 

“src” contiene mi código pulido y “scripts” contiene secuencias de comandos de Python únicas.

Me gustaría que todos los scripts tengan “../src” agregado a su sys.path, para que puedan acceder a los módulos bajo el árbol “src”. Una forma de hacer esto es escribir un archivo scripts / __ init__.py, con el contenido:

 scripts/__init__.py: import sys sys.path.append("../src") 

Esto funciona, pero tiene el efecto secundario no deseado de poner todos mis scripts en un paquete llamado “scripts”. ¿Hay alguna otra manera de hacer que todos mis scripts llamen automáticamente al código de inicialización anterior?

Podría editar la variable de entorno PYTHONPATH en mi .bashrc, pero quiero que mis scripts funcionen de forma inmediata, sin necesidad de que el usuario juegue con PYTHONPATH. Además, no me gusta tener que hacer cambios en la cuenta solo para dar cabida a este proyecto.

Incluso si tiene otros planes de distribución, podría valer la pena armar un setup.py básico en su carpeta src . De esa manera, puede ejecutar setup.py develop para que los distritos pongan un enlace a su código en su ruta predeterminada (lo que significa que cualquier cambio que realice se reflejará en el lugar sin tener que “reinstalar”, y todos los módulos “simplemente funcionarán, “no importa donde estén tus guiones). Sería un paso de una sola vez, pero sigue siendo un paso más que cero, por lo que depende de si eso es más problema que actualizar .bashrc . Si usa pip , el equivalente sería pip install -e /path/to/src .

La solución más robusta, especialmente si va a duplicar / crear versiones de estos scripts en las máquinas de varios desarrolladores, es hacer su trabajo de desarrollo dentro de un entorno virtual controlado. Resulta que virtualenv incluso tiene soporte incorporado para hacer tus propias personalizaciones de arranque . Parece que solo necesitaría un gancho after_install() para modificar el sitecustomize , sitecustomize , ejecutar pip install -e , o agregar un archivo plano .pth a los paquetes de sitio. El bootstrap personalizado podría vivir en su control de código fuente junto con los otros scripts, y debería ejecutarse una vez para cada configuración del desarrollador. También tendría los beneficios normales de usar virtualenv (control de versiones explícito de dependencias, aislamiento de la configuración de todo el sistema y estandarización entre máquinas dispares, por nombrar algunas).

Si realmente no quiere tener ningún paso de configuración y está dispuesto a ejecutar solo estos scripts desde el directorio del ‘proyecto’, entonces puede __init__.py un __init__.py como tal:

 project/ src/ some_module.py scripts/ __init__.py # special "magic" some_script.py 

Y estos son los que podrían verse tus archivos:

 # file: project/src/some_module.py print("importing %r" % __name__) def some_function(): print("called some_function() inside %s" % __name__) -------------------------------------------------------- # file: project/scripts/some_script.py import some_module if __name__ == '__main__': some_module.some_function() -------------------------------------------------------- # file: project/scripts/__init__.py import sys from os.path import dirname, abspath, join print("doing magic!") sys.path.insert(0, join(dirname(dirname(abspath(__file__))), 'src')) 

Entonces tendrías que ejecutar tus scripts así:

 [~/project] $ python -m scripts.some_script doing magic! importing 'some_module' called some_function() inside some_module 

¡Tener cuidado! Los scripts solo se pueden llamar así desde el project/ :

 [~/otherdir] $ python -m scripts.some_script ImportError: no module named scripts 

Para habilitar eso, está de nuevo en la edición de .bashrc , o usando una de las opciones anteriores. La última opción debería ser realmente un último recurso; como dijo @Simon, realmente estás luchando contra el idioma en ese momento.

Si desea que sus scripts sean ejecutables (supongo que desde la línea de comandos), tienen que estar en la ruta en algún lugar.

Sin embargo, algo suena extraño acerca de lo que estás tratando de hacer. ¿Puedes mostrarnos un ejemplo de lo que estás tratando de lograr exactamente?

puede agregar un archivo llamado ‘pathHack.py’ en el directorio del proyecto y poner algo como esto en él:

 import os import sys pkgDir = os.path.dirname(__file__) sys.path.insert(os.path.join(pkgDir, 'scripts') 

luego, en un archivo python en el directorio de su proyecto, comience por:

 import pathHack 

y ahora puedes importar cosas desde el directorio de scripts sin los ‘scripts’. prefijo. Si solo tiene un archivo en este directorio y no le importa ocultar este tipo de cosas, puede incluir este fragmento de código.