python: cambia la directory di lavoro degli script nella propria directory dello script
-
07-07-2019 - |
Domanda
Eseguo una shell Python da crontab ogni minuto:
* * * * * /home/udi/foo/bar.py
/ home / udi / foo
ha alcune sottodirectory necessarie, come / home / udi / foo / log
e / home / udi / foo / config
, a cui /home/udi/foo/bar.py
fa riferimento.
Il problema è che crontab
esegue lo script da una diversa directory di lavoro, quindi il tentativo di aprire ./log/bar.log
non riesce.
C'è un buon modo per dire allo script di cambiare la directory di lavoro nella propria directory dello script? Vorrei una soluzione che funzionasse per qualsiasi posizione dello script, piuttosto che dire esplicitamente allo script dove si trova.
Modifica
os.chdir(os.path.dirname(sys.argv[0]))
Era la soluzione elegante più compatta. Grazie per le risposte e le spiegazioni!
Soluzione
Questo cambierà la tua directory di lavoro corrente in modo che l'apertura dei relativi percorsi funzionerà:
import os
os.chdir("/home/udi/foo")
Tuttavia, hai chiesto come cambiare in qualunque directory si trova il tuo script Python, anche se non sai quale directory sarà quando stai scrivendo il tuo script. Per fare ciò, puoi usare le funzioni os.path
:
import os
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
Questo prende il nome del tuo script, lo converte in un percorso assoluto, quindi estrae la directory di quel percorso, quindi cambia in quella directory.
Altri suggerimenti
Puoi ottenere una versione più breve usando sys.path [0]
.
os.chdir(sys.path[0])
Da http://docs.python.org/library/sys.html # sys.path
Come inizializzato all'avvio del programma, il primo elemento di questo elenco,
path [0]
, è la directory che contiene lo script utilizzato invoca l'interprete Python
Non farlo.
I tuoi script e i tuoi dati non devono essere uniti in un'unica grande directory. Metti il ??tuo codice in una posizione nota ( pacchetti del sito
o / var / opt / udi
o qualcosa del genere) separato dai tuoi dati. Usa un buon controllo della versione sul tuo codice per assicurarti di avere le versioni attuali e precedenti separate l'una dall'altra in modo da poter ricorrere alle versioni precedenti e testare le versioni future.
Conclusione: non mescolare codice e dati.
I dati sono preziosi. Il codice va e viene.
Fornire la directory di lavoro come valore dell'argomento della riga di comando. È possibile fornire un valore predefinito come variabile di ambiente. Non dedurlo (o indovinarlo)
Renderlo un valore argomento richiesto e farlo.
import sys
import os
working= os.environ.get("WORKING_DIRECTORY","/some/default")
if len(sys.argv) > 1: working = sys.argv[1]
os.chdir( working )
Non " presumere " una directory basata sulla posizione del software. Non funzionerà bene a lungo termine.
Cambia il tuo comando crontab in
* * * * * (cd /home/udi/foo/ || exit 1; ./bar.py)
Il (...)
avvia una sotto-shell che la tua crond esegue come singolo comando. Il || exit 1
fa fallire il tuo cronjob nel caso in cui la directory non sia disponibile.
Sebbene le altre soluzioni possano essere più eleganti a lungo termine per i tuoi script specifici, il mio esempio potrebbe essere comunque utile nei casi in cui non è possibile modificare il programma o il comando che si desidera eseguire.