Скрипт Python не работает в crontab, вызывая pysaunter

Я прочитал несколько сообщений и много статей, в которых подробно описывается, что сценарии в задании cron должны сохранять переменные среды, необходимые для запуска внутри самого сценария, из-за открытия оболочек в cron. Моя ситуация уникальна тем, что все мои переменные пути установлены, как описано, что, в свою очередь, успешно вызовет яйцо python pysaunter, используя subprocess.call (), но, похоже, оттуда он не работает. Это приводит к прерыванию всего процесса в работе cron.

Для ясности, вот шаги, о которых я говорю:

1) cronjob calls run_test.py -n foo
2) run_test.py sets the environment variables correctly 
(cur_shell_path=sys.path (converted to proper path string, not shown here)
 my_env= os.environ.copy()
 my_env["PATH"] = my_env["PATH"] + cur_shell_path)
3) run_test.py calls subprocess.call("pysaunter -m foo -v", env=my_env, shell=True)

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

ImportError: no module named helpers

Я пытался добавить этот путь в среду несколько раз, но мне не удалось найти каталог, содержащий helpers.py. Команда pysaunter -m foo -v работает нормально при вызове из интерактивной оболочки.

Мне не удалось найти много помощи по pysaunter, поэтому я предполагаю, что слишком много подробностей pysaunter здесь было бы ненужным. Однако, если вы знаете больше о pysaunter, дайте мне знать, если вам потребуется дополнительная информация. Я не знаю, чем поделиться.

Я также прочитал много сообщений, в которых обсуждается возможность изменения поведения оболочки по умолчанию путем редактирования файла .profile / .bash_profile. Я попытался найти место, которое сделало бы мои переменные пути глобально доступными, но ничего не нашел. Я не знаю, как это делается, и это может решить мою проблему, поэтому, если вы что-то знаете об этом, дайте мне знать.

Последнее замечание, это работает на Mac 10.7.5.


person derigible    schedule 11.07.2013    source источник


Ответы (2)


После долгих проб и ошибок, множества статей на stackoverflow.com и других руководств в Интернете, и с помощью Perl-скрипта я обнаружил, что делает нечто подобное, я смог выяснить, что нужно сделать, чтобы это работало. .

Вот шаги, чтобы убедиться, что все настроено правильно:

  1. Убедитесь, что у вас есть необходимые переменные в PYTHONPATH (их можно найти здесь и здесь, а для подробнее. перейдите сюда) внутри .profile или .bash_profile для любой оболочки. вы хотите протестировать свой сценарий, чтобы убедиться, что он работает.

  2. Отредактируйте ваш crontab, включив в него каталоги, необходимые для запуска вашего скрипта в задании cron (найдено здесь и здесь).

    a) Обязательно включите корневой каталог в переменную PATH (.), как описано в здесь. По сути, если вы запускаете исполняемый файл с вашей командой, он должен иметь возможность найти корень или каталог, в котором хранится исполняемый файл, а также, вероятно, следующие: (/ sbin: / bin: / usr / sbin: / usr / bin).

  3. В вашем файле crontab создайте задание cron, которое изменит текущий каталог на каталог, в котором вы успешно запускали сценарий ранее (например, / Users / user / Documents / foo).

    а) Это будет выглядеть следующим образом:

    * * * * cd /Users/user/Documents/foo; bar -l doSomething -v 
    
  4. Поскольку моя проблема связана именно с вызовом исполняемого файла, необходимо отметить, что существует несколько способов написания скрипта Python для запуска (хотя в процессе обнаружения я узнал, что это работает для любого вызова, сделанного с использованием подпроцесса в cron).

    Первый способ выглядит так:

    ... #some script calls
    my_env = os.environ.copy()
    my_env["PYTHONPATH"] = "{}:{}".format(os.environ["PATH"] ,"<path you want to include>")
    os.chdir("<path/to/desired/directory>")
    subprocess.Popen(<call_as_string>, env=my_env, shell=True)
    

    А второй выглядит так:

    ... #some script calls
    os.environ["PYTHONPATH"] = "{}:{}".format(os.environ["PATH"] ,"<path you want to include>")
    os.chdir("<path/to/desired/directory>")
    subprocess.Popen(<call_as_list_of_arguments)
    

    Поскольку исполняемому файлу нужен путь к каталогу помощников, включенному в оболочку, из которой он был вызван, было необходимо передать переменную среды в исполняемый файл, как описано в здесь. Однако я обнаружил, что изменение переменной PATH в среде не работает для задания cron, а установка PYTHONPATH работает. Я прочитал здесь, что переменная PATH используется оболочкой только для ищите исполняемые файлы, поэтому для новой оболочки внутри задания cron вам необходимо передать оболочке PYTHONPATH для поиска новых модулей Python. (Это также объясняется в документации Python.)

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

person derigible    schedule 16.07.2013

То, что вы сказали, не имеет смысла.

Вы говорите shell_env = sys.path. sys.path - это список папок, в которых python будет искать модули, а не отображение переменных среды!

Затем вы используете это в subprocess.call. Возможно, вы хотели написать env=my_env.

Это следующая проблема. Во-первых, PATH должен быть списком папок, разделенных ':'. Вы просто добавляете shell_path к последней папке.

Наконец, python использует PYTHONPATH в качестве списка для поиска модулей python (похоже, это проблема, с которой вы столкнулись.)

person korylprince    schedule 11.07.2013
comment
Спасибо, что указали на мою проблему, теперь я исправил ее, чтобы показать, что my_env передается. Кроме того, на машинах на базе Unix двоеточие (:) используется для разделения значений путей, так что это не может быть проблемой. Наконец, Pythonpath используется для поиска в локальном каталоге, который в Unix определяется тем, где находилась оболочка запущен. Поскольку задания cron вызывают неинтерактивную оболочку, которая запускается не из правильного каталога и не читает .profile или .bash_profile, путь не добавляется и, следовательно, Pythonpath не устанавливается. - person derigible; 11.07.2013
comment
Вы были правы насчет толстой кишки. Я исправил это. Вам нужно установить PYTHONPATH в задании cron. Вы можете создать сценарий-оболочку, который устанавливает PYTHONPATH в желаемый каталог, а затем вызывает сценарий python. - person korylprince; 16.07.2013