питон:Измените рабочий каталог скриптов на собственный каталог скрипта

StackOverflow https://stackoverflow.com/questions/1432924

  •  07-07-2019
  •  | 
  •  

Вопрос

Я запускаю оболочку 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]))

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

Это было полезно?

Решение

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

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)

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

Другие советы

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

os.chdir(sys.path[0])

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

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

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

Ваши скрипты и ваши данные не должны быть объединены в один большой каталог.Поместите свой код в какое-нибудь известное место (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 )

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top