Я запускаю оболочку 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
не удалась.
Есть ли хороший способ сказать сценарию изменить рабочий каталог на собственный каталог сценария? Я хотел бы найти решение, которое будет работать для любого местоположения сценария, а не явно указывать сценарию, где оно находится.
РЕДАКТИРОВАТЬ:
os.chdir(os.path.dirname(sys.argv[0]))
Было самым компактным элегантным решением. Спасибо за ваши ответы и объяснения!
python
working-directory
Адам Матан
источник
источник
crontab
прецедентом: обаsys.argv[0]
и__file__
терпят неудачу, если скрипт выполняется с помощьюexecfile()
;inspect
решение может быть использовано вместо.Ответы:
Это изменит ваш текущий рабочий каталог, чтобы открывать относительные пути:
Однако вы спросили, как перейти в любой каталог, в котором находится ваш скрипт Python, даже если вы не знаете, какой каталог будет при написании скрипта. Для этого вы можете использовать
os.path
функции:Это берет имя файла вашего скрипта, преобразует его в абсолютный путь, затем извлекает каталог этого пути, а затем изменяется в этот каталог.
источник
__file__
вместоsys.argv[0]
.os.chdir(os.path.dirname(__file__))
?__file__
происходит сбой в «замороженных» программах (созданных с использованием py2exe, PyInstaller, cx_Freeze).sys.argv[0]
работает. @ChrisDown: если вы хотите перейти по символическим ссылкам;os.path.realpath()
может быть использован.__file__
это еще не абсолютный путь, и пользователь изменил рабочий каталог, тоos.path.abspath
все равно произойдет сбой.Вы можете получить более короткую версию, используя
sys.path[0]
.С http://docs.python.org/library/sys.html#sys.path
источник
Не делай этого.
Ваши сценарии и ваши данные не должны быть объединены в один большой каталог. Поместите свой код в некотором известном месте (
site-packages
или/var/opt/udi
или что - то) отдельно от ваших данных. Используйте хороший контроль версий в своем коде, чтобы убедиться, что у вас есть текущие и предыдущие версии, отделенные друг от друга, чтобы вы могли вернуться к предыдущим версиям и протестировать будущие версии.Итог: не смешивайте код и данные.
Данные драгоценны. Код приходит и уходит.
Укажите рабочий каталог в качестве значения аргумента командной строки. Вы можете указать значение по умолчанию в качестве переменной среды. Не выводи это (или не догадывайся об этом)
Сделайте это обязательным значением аргумента и сделайте это.
Не «предполагайте» каталог, основанный на местоположении вашего программного обеспечения. Это не сработает в долгосрочной перспективе.
источник
Измените команду crontab на
(...)
Начинает подоболочку , что ваш crond выполняется в качестве одной команды.|| exit 1
Вызывает ваш cronjob к сбою в случае, если каталог недоступен.Хотя другие решения могут быть более элегантными в долгосрочной перспективе для ваших конкретных сценариев, мой пример может быть полезен в тех случаях, когда вы не можете изменить программу или команду, которую хотите выполнить.
источник
|| exit 1
. Приятно видеть это. Хотя мне непонятно, почему бы тебе просто не занятьсяcd /home/udi/foo/ && ./bar.py
exit 1
ваш crond будет уведомлен об ошибке, и в большинстве случаев отправит уведомление по электронной почте о сбое.