python: изменить рабочий каталог скриптов на собственный каталог скрипта - PullRequest
143 голосов
/ 16 сентября 2009

Я запускаю оболочку Python из crontab каждую минуту:

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

/home/udi/foo имеет несколько необходимых подкаталогов, таких как /home/udi/foo/log и /home/udi/foo/config, к которым относится /home/udi/foo/bar.py.

Проблема в том, что crontab запускает скрипт из другого рабочего каталога, поэтому попытка открыть ./log/bar.log не удалась.

Есть ли хороший способ указать сценарию изменить рабочий каталог на собственный каталог сценария? Мне бы хотелось найти решение, которое будет работать для любого местоположения сценария, а не явно указывать сценарию, где оно находится.

EDIT:

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

Было самым компактным элегантным решением. Спасибо за ваши ответы и объяснения!

Ответы [ 4 ]

172 голосов
/ 16 сентября 2009

Это изменит вашу текущую рабочую директорию на так, чтобы открытие относительных путей работало:

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

Однако вы спросили, как перейти в каталог, в котором находится ваш скрипт Python, даже если вы не знаете, какой каталог будет при написании скрипта. Для этого вы можете использовать функции os.path:

import os

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

Это берет имя файла вашего скрипта, преобразует его в абсолютный путь, затем извлекает каталог этого пути, затем изменяет в этот каталог.

43 голосов
/ 03 февраля 2012

Вы можете получить более короткую версию, используя sys.path[0].

os.chdir(sys.path[0])

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

Как инициализируется при запуске программы, первый элемент этого списка, path[0], каталог, содержащий скрипт, который использовался для вызвать интерпретатор Python

19 голосов
/ 16 сентября 2009

Не делай этого.

Ваши сценарии и ваши данные не должны быть объединены в один большой каталог. Поместите ваш код в какое-то известное место (site-packages или /var/opt/udi или что-то еще) отдельно от ваших данных. Используйте хороший контроль версий в своем коде, чтобы убедиться, что у вас есть текущие и предыдущие версии, отделенные друг от друга, чтобы вы могли вернуться к предыдущим версиям и проверить будущие версии.

Итог: не смешивайте код и данные.

Данные драгоценны. Код приходит и уходит.

Предоставить рабочий каталог в качестве значения аргумента командной строки. Вы можете указать значение по умолчанию в качестве переменной среды. Не делай вывод (или не угадывай)

Сделайте это обязательным значением аргумента и сделайте это.

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

Не «предполагайте» каталог, основанный на расположении вашего программного обеспечения. В долгосрочной перспективе это не сработает.

17 голосов
/ 31 января 2013

Измените команду crontab на

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

(...) запускает под-оболочку, которую ваш crond выполняет как одна команда. || exit 1 приводит к сбою вашего cronjob в случае, если каталог недоступен.

Хотя другие решения могут быть более элегантными в долгосрочной перспективе для ваших конкретных сценариев, мой пример может быть полезен в тех случаях, когда вы не можете изменить программу или команду, которую хотите выполнить.

...