Ich starte jede Minute eine Python-Shell von crontab:
* * * * * /home/udi/foo/bar.py
/home/udi/foo
hat einige notwendige Unterverzeichnisse, wie /home/udi/foo/log
und /home/udi/foo/config
, die sich /home/udi/foo/bar.py
beziehen.
Das Problem ist, dass crontab
das Skript in einem anderen Arbeitsverzeichnis ausgeführt wird, sodass der Versuch, es zu öffnen, ./log/bar.log
fehlschlägt.
Gibt es eine gute Möglichkeit, das Skript anzuweisen, das Arbeitsverzeichnis in das eigene Verzeichnis des Skripts zu ändern? Ich würde mir eine Lösung vorstellen, die für jeden Skriptstandort funktioniert, anstatt dem Skript explizit mitzuteilen, wo es sich befindet.
BEARBEITEN:
os.chdir(os.path.dirname(sys.argv[0]))
War die kompakteste elegante Lösung. Vielen Dank für Ihre Antworten und Erklärungen!
python
working-directory
Adam Matan
quelle
quelle
crontab
Anwendungsfall: beidessys.argv[0]
und__file__
fehlgeschlagen, wenn das Skript mit ausgeführt wirdexecfile()
; Stattdessen könnte eineinspect
Lösung auf Basis verwendet werden.Antworten:
Dadurch wird Ihr aktuelles Arbeitsverzeichnis in geändert, sodass das Öffnen relativer Pfade funktioniert:
Sie haben jedoch gefragt, wie Sie in das Verzeichnis wechseln sollen, in dem sich Ihr Python-Skript befindet, auch wenn Sie nicht wissen, in welchem Verzeichnis sich das Skript befindet. Dazu können Sie folgende
os.path
Funktionen verwenden:Dies nimmt den Dateinamen Ihres Skripts, konvertiert ihn in einen absoluten Pfad, extrahiert dann das Verzeichnis dieses Pfads und wechselt dann in dieses Verzeichnis.
quelle
__file__
anstelle vonsys.argv[0]
.os.chdir(os.path.dirname(__file__))
?__file__
schlägt in "eingefrorenen" Programmen fehl (erstellt mit py2exe, PyInstaller, cx_Freeze).sys.argv[0]
funktioniert. @ChrisDown: Wenn Sie Symlinks folgen möchten;os.path.realpath()
könnte verwendet werden.__file__
noch kein absoluter Pfad ist und der Benutzer das Arbeitsverzeichnis geändert hat, schlägt diesos.path.abspath
trotzdem fehl.Sie können eine kürzere Version erhalten, indem Sie verwenden
sys.path[0]
.Von http://docs.python.org/library/sys.html#sys.path
quelle
Tu das nicht.
Ihre Skripte und Ihre Daten sollten nicht in einem großen Verzeichnis zusammengefasst werden. Setzen Sie den Code in irgendeiner bekannten Position (
site-packages
oder/var/opt/udi
oder etwas) getrennt von Ihren Daten. Verwenden Sie eine gute Versionskontrolle für Ihren Code, um sicherzustellen, dass aktuelle und frühere Versionen voneinander getrennt sind, damit Sie auf frühere Versionen zurückgreifen und zukünftige Versionen testen können.Fazit: Mischen Sie Code und Daten nicht.
Daten sind wertvoll. Code kommt und geht.
Geben Sie das Arbeitsverzeichnis als Befehlszeilenargumentwert an. Sie können einen Standard als Umgebungsvariable angeben. Leiten Sie es nicht ab (oder raten Sie es)
Machen Sie es zu einem erforderlichen Argumentwert und tun Sie dies.
Nehmen Sie kein Verzeichnis an, das auf dem Speicherort Ihrer Software basiert. Es wird auf lange Sicht nicht gut funktionieren.
quelle
Ändern Sie Ihren crontab-Befehl in
Das
(...)
startet eine Sub-Shell, die Ihr Crond als einzelnen Befehl ausführt. Das|| exit 1
bewirkt , dass Ihr cronjob im Fall fehlschlagen , dass das Verzeichnis nicht verfügbar ist.Obwohl die anderen Lösungen auf lange Sicht für Ihre spezifischen Skripte eleganter sind, kann mein Beispiel dennoch nützlich sein, wenn Sie das Programm oder den Befehl, den Sie ausführen möchten, nicht ändern können.
quelle
|| exit 1
. Es ist erfrischend, das zu sehen. Obwohl ich mich fragen muss, warum Sie es nicht einfach tun würdencd /home/udi/foo/ && ./bar.py
exit 1
Ihr crond über einen Fehler benachrichtigt und in den meisten Fällen eine E-Mail-Benachrichtigung über den Fehler gesendet .