python: cambie el directorio de trabajo de los scripts al directorio propio del script

StackOverflow https://stackoverflow.com/questions/1432924

  •  07-07-2019
  •  | 
  •  

Pregunta

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 , al que se refiere /home/udi/foo/bar.py .

El problema es que crontab ejecuta el script desde un directorio de trabajo diferente, por lo que falla al intentar abrir ./log/bar.log .

¿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 funcionara para cualquier ubicación de script, en lugar de decirle explícitamente al script dónde está.

EDIT:

os.chdir(os.path.dirname(sys.argv[0]))

Fue la solución elegante más compacta. ¡Gracias por sus respuestas y explicaciones!

¿Fue útil?

Solución

Esto cambiará su directorio de trabajo actual para que la apertura de rutas relativas funcione:

import os
os.chdir("/home/udi/foo")

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 escriba su script. Para hacer esto, puede usar las funciones os.path :

import os

abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)

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.

Otros consejos

Puede obtener una versión más corta utilizando sys.path [0] .

os.chdir(sys.path[0])

De http://docs.python.org/library/sys.html # sys.path

  

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

No hagas esto.

Sus scripts y sus datos no deben combinarse en un directorio grande. Ponga su código en alguna ubicación conocida ( paquetes de sitio o / var / opt / udi o algo) separado de sus datos. Utilice 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.

Conclusión: 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.

import sys
import os
working= os.environ.get("WORKING_DIRECTORY","/some/default")
if len(sys.argv) > 1: working = sys.argv[1]
os.chdir( working )

No "asuma" un directorio basado en la ubicación de su software. No funcionará bien a largo plazo.

Cambie su comando crontab a

* * * * * (cd /home/udi/foo/ || exit 1; ./bar.py)

El (...) inicia un sub-shell que su crond ejecuta como un solo comando. El || la salida 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 comando que desea ejecutar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top