Ejecuto un shell de Python desde crontab cada minuto:
* * * * * /home/udi/foo/bar.py
/home/udi/footiene algunos subdirectorios necesarios, como /home/udi/foo/logy /home/udi/foo/config, que se /home/udi/foo/bar.pyrefiere a.
El problema es que crontabejecuta el script desde un directorio de trabajo diferente, por lo que ./log/bar.logfalla al intentar abrirlo .
¿Hay una buena manera de decirle al script que cambie el directorio de trabajo al propio directorio del script? Me gustaría una solución que funcione para cualquier ubicación de script, en lugar de decirle explícitamente dónde está.
EDITAR:
os.chdir(os.path.dirname(sys.argv[0]))
Fue la solución elegante más compacta. Gracias por sus respuestas y explicaciones!
python
working-directory
Adam Matan
fuente
fuente

crontabel caso de uso: ambossys.argv[0]y__file__fallan si el script se ejecuta usandoexecfile();inspectbasada en solución podría usarse en su lugar.Respuestas:
Esto cambiará su directorio de trabajo actual a para que funcione abrir rutas relativas:
Sin embargo, usted preguntó cómo cambiar a cualquier directorio en el que se encuentre su script Python, incluso si no sabe qué directorio será cuando esté escribiendo su script. Para hacer esto, puede usar las
os.pathfunciones:Esto toma el nombre de archivo de su script, lo convierte en una ruta absoluta, luego extrae el directorio de esa ruta, luego cambia a ese directorio.
fuente
__file__lugar desys.argv[0].os.chdir(os.path.dirname(__file__))?__file__falla en programas "congelados" (creados con py2exe, PyInstaller, cx_Freeze).sys.argv[0]trabajos. @ChrisDown: si desea seguir enlaces simbólicos;os.path.realpath()puede ser usado.__file__no es una ruta absoluta y el usuario ha cambiado el directorio de trabajo,os.path.abspathfallará de todos modos.Puede obtener una versión más corta usando
sys.path[0].De http://docs.python.org/library/sys.html#sys.path
fuente
No hagas esto.
Sus scripts y sus datos no deben combinarse en un directorio grande. Poner su código en alguna ubicación conocida (
site-packageso/var/opt/udio algo así) separado de sus datos. Use un buen control de versiones en su código para asegurarse de que tiene versiones actuales y anteriores separadas entre sí para que pueda recurrir a versiones anteriores y probar versiones futuras.En pocas palabras: no mezcle código y datos.
Los datos son preciosos. El código va y viene.
Proporcione el directorio de trabajo como un valor de argumento de línea de comando. Puede proporcionar un valor predeterminado como variable de entorno. No lo deduzca (ni lo adivine)
Conviértalo en un valor de argumento requerido y haga esto.
No "asuma" un directorio basado en la ubicación de su software. No funcionará bien a la larga.
fuente
Cambie su comando crontab a
El
(...)comienza una sub-shell que ejecuta sus crond como un solo comando. Esto|| exit 1hace que su cronjob falle en caso de que el directorio no esté disponible.Aunque las otras soluciones pueden ser más elegantes a largo plazo para sus scripts específicos, mi ejemplo aún podría ser útil en los casos en que no pueda modificar el programa o el comando que desea ejecutar.
fuente
|| exit 1. Es refrescante ver esto. Aunque tengo que preguntarme por qué no lo harías simplementecd /home/udi/foo/ && ./bar.pyexit 1su crond será notificado de un error y, en la mayoría de los casos, enviará una notificación por correo electrónico del error.