Ejecuto un shell de Python desde crontab cada minuto:
* * * * * /home/udi/foo/bar.py
/home/udi/foo
tiene algunos subdirectorios necesarios, como /home/udi/foo/log
y /home/udi/foo/config
, que se /home/udi/foo/bar.py
refiere a.
El problema es que crontab
ejecuta el script desde un directorio de trabajo diferente, por lo que ./log/bar.log
falla 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
crontab
el caso de uso: ambossys.argv[0]
y__file__
fallan si el script se ejecuta usandoexecfile()
;inspect
basada 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.path
funciones: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.abspath
fallará 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-packages
o/var/opt/udi
o 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 1
hace 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.py
exit 1
su crond será notificado de un error y, en la mayoría de los casos, enviará una notificación por correo electrónico del error.