web-dev-qa-db-fra.com

python: change le répertoire de travail du script en son propre répertoire

Je lance un python Shell à partir de crontab chaque minute:

* * * * * /home/udi/foo/bar.py

/home/udi/foo a quelques sous-répertoires nécessaires, comme /home/udi/foo/log et /home/udi/foo/config, lequel /home/udi/foo/bar.py fait référence à.

Le problème est que crontab exécute le script à partir d’un répertoire de travail différent, ce qui tente d’ouvrir ./log/bar.log échoue.

Y a-t-il un bon moyen de dire au script de changer le répertoire de travail en son propre répertoire? J'aimerai une solution qui fonctionnerait pour n'importe quel emplacement de script, plutôt que de dire explicitement le script où il se trouve.

EDIT:

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

Était la solution élégante la plus compacte. Merci pour vos réponses et explications!

146
Adam Matan

Cela modifiera votre répertoire de travail actuel pour que l'ouverture des chemins relatifs fonctionne:

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

Cependant, vous avez demandé comment changer le répertoire dans lequel se trouvait votre script Python, même si vous ne savez pas quel répertoire cela sera lors de l'écriture de votre script. Pour ce faire, peut utiliser le os.path les fonctions:

import os

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

Cela prend le nom de fichier de votre script, le convertit en chemin absolu, extrait le répertoire de ce chemin, puis le modifie.

177
Eli Courtwright

Vous pouvez obtenir une version plus courte en utilisant sys.path[0].

os.chdir(sys.path[0])

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

Initialisé au démarrage du programme, le premier élément de cette liste, path[0], est le répertoire contenant le script utilisé pour appeler l’interprète Python

44
xverges

Ne fais pas ça.

Vos scripts et vos données ne doivent pas être écrasés dans un seul grand répertoire. Placez votre code dans un emplacement connu (site-packages ou /var/opt/udi ou quelque chose) séparé de vos données. Utilisez un bon contrôle de version sur votre code pour vous assurer que les versions actuelles et précédentes sont séparées les unes des autres afin de pouvoir revenir aux versions précédentes et tester les versions futures.

Conclusion: ne mêlez pas le code et les données.

Les données sont précieuses. Le code va et vient.

Indiquez le répertoire de travail comme valeur d'argument de ligne de commande. Vous pouvez fournir une valeur par défaut en tant que variable d'environnement. Ne le déduisez pas (ou devinez-le)

Faites-en une valeur d'argument obligatoire et faites-le.

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

Ne supposez pas un répertoire basé sur l’emplacement de votre logiciel. Cela ne marchera pas bien à long terme.

21
S.Lott

Changez votre commande crontab en

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

Le (...) lance un sous-shell que votre crond exécute en une seule commande. Le || exit 1 _ provoque l’échec de votre travail cron dans le cas où le répertoire est indisponible.

Bien que les autres solutions puissent être plus élégantes à long terme pour vos scripts spécifiques, mon exemple pourrait néanmoins être utile dans les cas où vous ne pouvez pas modifier le programme ou la commande que vous souhaitez exécuter.

17
Ruud Althuizen