Solución:
Recientemente cambié de canopy a Anaconda precisamente para evitar tener que activar un env en trabajos cron. Anaconda lo hace muy simple, basado en la variable de entorno PATH. (Estoy usando miniconda, no la instalación completa de Anaconds, pero creo que anaconda debería funcionar de la misma manera)
Hay dos enfoques diferentes que he probado;
-
Agregue un shebang en su script de Python, main.py
#!/home/users/user_name/miniconda2/envs/my_env/bin/python
-
Agregue PATH a la parte superior de su crontab
PATH=/home/users/user_name/miniconda2/envs/my_env/bin
Actualizar:
La respuesta de Jérôme y los comentarios de cbarrick son correctos. Acabo de quemarme usando el enfoque anterior en un Conda env que necesitaba pynco,
que necesita el entorno completo de conda para encontrar el nco
comandos, como ncks, ncrcat.
Resuelto ejecutando un script bash desde cron que llama a conda activo primero.
No llames sh
pero bash
. source
es un comando bash.
- sh scripts/my_script.bash
+ bash scripts/my_script.bash
O solo
chmod +x scripts/my_script.bash
./scripts/my_script.bash
desde que agregaste el bash shebang.
Después de MUCHO violín conseguí crontab
para activar mi entorno conda con conda activate my_env
y ejecute el intérprete de Python dentro de ese entorno.
Tenga en cuenta que estoy usando Ubuntu 18.04.
Fondo
-
Cuando el instalador de Anaconda inicializa conda, agrega un fragmento al final del
~/.bashrc
expediente. Este archivo se ejecuta cada vez que el usuario abrebash
interactivamente. El fragmento permite al usuario ejecutarconda
comandos (es decirconda activate my_env
) debash
. -
El instalador de Anaconda v2020.02 agregó lo siguiente
conda
fragmento en~/.bashrc
:
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/opt/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
eval "$__conda_setup"
else
if [ -f "/opt/anaconda3/etc/profile.d/conda.sh" ]; then
. "/opt/anaconda3/etc/profile.d/conda.sh"
else
export PATH="/opt/anaconda3/bin:$PATH"
fi
fi
unset __conda_setup
# <<< conda initialize <<<
- El camino
/opt/anaconda3/
para ser reemplazado con la referencia correcta: generalmente/home/USERNAME/anaconda3/
.
El problema
Abastecimiento ~/.bashrc
en crontab -e
no funcionará (al menos no en Ubuntu).
Explicación:
- En Ubuntu,
~/.bashrc
tiene la siguiente línea (o similar) al principio del archivo:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
- Esto significa que si intentamos obtener el
~/.bashrc
presentar encrontab
, el resto de.bashrc
el archivo no se ejecutará porquecrontab
no se ejecuta de forma interactiva (consulte otra publicación sobre este tema). Lo que significa que elconda
el fragmento mencionado anteriormente nunca será ejecutado porcrontab
incluso si obtenemos~/.bashrc
.
_________ Solución de trabajo _________
La solución que he encontrado es copiar el conda
fragmento en un archivo separado.
1. Copiar el conda
fragmento de ~/.bashrc
para ~/.bashrc_conda
Copie el fragmento mencionado anteriormente en otro archivo, por ejemplo ~/.bashrc_conda
.
Asegurarse de que:
- El usuario que ejecuta el cronjob tiene permiso para leer este archivo.
- Otros usuarios no pueden escribir en este archivo (riesgo de seguridad).
2. En crontab -e
inserte 2 líneas para ejecutar bash
en lugar de sh
y a la fuente ~/.bashrc_conda
Correr crontab -e
y agregue las siguientes 2 líneas antes del cronjob:
SHELL=/bin/bash
BASH_ENV=~/.bashrc_conda
Explicación:
-
SHELL=/bin/bash
significa quecrontab
ejecutará los cronjobs a través debash
en lugar desh
(defecto). Ver publicación. -
BASH_ENV=~/.bashrc_conda
fuentes elconda
fragmento debash
contenerchrontab
. Ver publicación y publicación.
3 en crontab -e
insertar en la línea cronjob conda activate my_env;
antes de lo deseado .py
ejecución de script
Ejemplo de entrada para un script que se ejecutaría al mediodía a las 12:30 todos los días dentro del entorno de conda deseado:
30 12 * * * conda activate my_env; python /path/to/script.py
Aviso conda activate my_env;
antes del comando para ejecutar el intérprete de Python.
_______________
Y voilà, funcionó.
¿Algún inconveniente?
Si el conda
fragmento en .bashrc
se actualiza por un conda
actualización, por supuesto, no se reflejará en la .bashrc_conda
expediente. Es posible que deba buscar actualizaciones de vez en cuando.
También se podría agregar ; conda deactivate
en el fin de ese cronjob, pero esto puede ser redundante.