Пакеты Python не найдены при выполнении cron-задач, даже после использования sudo pip install.

Вопрос или проблема

Вот моя команда crontab:

*/15 * * * * cd /home/ec2-user/SageMaker && /bin/bash /home/ec2-user/SageMaker/churn_end_to_end_pipeling_actionable.sh

В моем письме вот ошибки, которые я получаю:

Message-Id: <[email protected]>
X-Authentication-Warning: ip-172-16-124-135.ec2.internal: ec2-user set sender to root using -f
From: [email protected] (Cron Daemon)
To: [email protected]
Subject: Cron <ec2-user@ip-172-16-124-135> cd /home/ec2-user/SageMaker && /bin/bash /home/ec2-user/SageMaker/churn_end_to_end_pipeling_actionable.sh
Content-Type: text/plain; charset=UTF-8
Auto-Submitted: auto-generated
X-Cron-Env: <LANG=en_US.UTF-8>
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/home/ec2-user>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=ec2-user>
X-Cron-Env: <USER=ec2-user>

Traceback (most recent call last):
  File "feature_engineering.py", line 9, in <module>
    import seaborn as sns
ImportError: No module named seaborn
Traceback (most recent call last):
  File "generate_churn_outputs_actionable.py", line 5, in <module>
    from xgboost import XGBClassifier
ImportError: No module named xgboost

Я не уверен, почему я сталкиваюсь с этой ошибкой, так как я выполнял sudo -H pip install <package> перед запуском задания cron.

Также вот содержимое моего bash-скрипта и python-скриптов, на которые он ссылается:

Bash:

#!/bin/bash

python feature_engineering.py 
python generate_churn_outputs_actionable.py 1

Скрипт 1 и 2:

#! /home/ec2-user/anaconda3/envs/JupyterSystemEnv/bin/python

Буду признателен за любую помощь. Если я что-то упустил, дайте знать, и я добавлю это.

У меня была такая же проблема на Ubuntu 18.04, и явный путь в crontab не сработал. По какой-то причине cron не работал, а sudo из моего аккаунта работал. Я предполагал, что они должны быть одинаковыми, но, увы, это не так. Я пришел к выводу, что это проблема с переменными окружения.

Вы можете смоделировать проблему с cron в sudo, выполнив следующее:

sudo bash -c "HOME=FOO;python3 -c \"import xgboost\""

Для меня решением было вызвать shell-скрипт из crontab, который затем выполняет python-скрипт. Также нужно было установить переменные окружения HOME и PYTHONPATH:

crontab:

# Выполнить shell-скрипт и перенаправить stdout и stderr в лог-файл
# Это позволит вам увидеть, что происходит в реальном времени
* * * * * <ваш_путь>/yourscript.sh  >> <ваш_путь>yourscript_cron.log 2>&1

yourscript.sh:

#!/bin/bash
echo yourscript.sh вызван: `date`
HOME=<ваша_домашняя_директория>
PYTHONPATH=<путь_к_пакетам_распределения>
cd <путь_к_вашему_python_скрипту>
<python_исполняемый_файл> ./<ваш_python_скрипт> 2>&1 1>/dev/null

Ответ или решение

Приветствую вас!

Ситуация, с которой вы столкнулись, довольно распространена при работе с cron и Python-пакетами на системах, использующих среду выполнения, например, Anaconda или виртуальные окружения. Давайте разберемся с причиной проблемы и предложим решения.

1. Причина проблемы

Основная причина ваших ошибок, таких как ImportError: No module named seaborn и ImportError: No module named xgboost, заключается в том, что cron выполняет ваши задачи в более ограниченной среде, чем ваша обычная пользовательская среда.

  • Привилегии и окружение: Когда вы выполняете команды с sudo, Python использует системные модули и установленные пакеты в зависимости от текущего окружения пользователя. Когда вы запускаете скрипты из cron, они могут не видеть те же пути, что и ваш пользовательский сеанс, так как cron использует ограниченный набор переменных среды (например, PATH).

  • Отсутствие переменных окружения: Для скриптов, которые требуют специфические переменные окружения, такие как PYTHONPATH, cron может не обнаружить эти переменные, если вы не установите их вручную в вашем скрипте.

2. Решения

Использование полного пути к интерпретатору Python

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

#! /home/ec2-user/anaconda3/envs/JupyterSystemEnv/bin/python

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

Создание оболочки для скрипта

Рекомендуется создать оболочку для вашего скрипта и явно установить все нужные переменные среды. Вот как это можно сделать:

  1. Создайте новый shell-скрипт, например run_scripts.sh:
#!/bin/bash

# Установите переменные окружения
export HOME=/home/ec2-user
export PYTHONPATH=/home/ec2-user/anaconda3/envs/JupyterSystemEnv/lib/python3.X/site-packages

# Перейдите в директорию со скриптом
cd /home/ec2-user/SageMaker

# Запустите Python-скрипты
/home/ec2-user/anaconda3/envs/JupyterSystemEnv/bin/python feature_engineering.py 
/home/ec2-user/anaconda3/envs/JupyterSystemEnv/bin/python generate_churn_outputs_actionable.py 1

Не забудьте заменить python3.X на вашу актуальную версию Python.

  1. Затем измените ваш crontab, чтобы он вызывал этот скрипт:
*/15 * * * * /home/ec2-user/SageMaker/run_scripts.sh >> /home/ec2-user/SageMaker/script.log 2>&1

Это перенаправит стандартный вывод и ошибки вашего скрипта в лог-файл, что поможет вам следить за выполнением и отладкой.

Проверка прав доступа

Убедитесь, что у вас есть необходимые права доступа на выполнение вашего скрипта. Вы можете сделать это с помощью:

chmod +x /home/ec2-user/SageMaker/run_scripts.sh

3. Заключение

Изменения, предложенные в этом ответе, должны помочь вам избежать ошибок импорта пакетов при запуске скриптов через cron. Убедитесь, что все пути прописаны корректно, а переменные окружения установлены.

Если у вас остаются вопросы или потребуются дальнейшие разъяснения, не стесняйтесь задавать их. Удачи в вашей работе!

Оцените материал
Добавить комментарий

Капча загружается...