Programación de trabajos con python-crontab

P

¿Qué es Crontab?

Cron es una utilidad de software que nos permite programar tareas en sistemas similares a Unix. El nombre se deriva de la palabra griega “Chronos”, que significa “tiempo”.

Las tareas en Cron se definen en un crontab, que es un archivo de texto que contiene los comandos a ejecutar. La sintaxis utilizada en un crontab se describe a continuación en este artículo.

Python nos presenta el módulo crontab para administrar trabajos programados a través de Cron. Las funciones disponibles en él nos permiten acceder a Cron, crear trabajos, establecer restricciones, eliminar trabajos y más. En este artículo mostraremos cómo usar estas operaciones desde dentro de su código Python.

Para el lector interesado, la página de ayuda oficial se puede encontrar en https://pypi.python.org/pypi/python-crontab.

Sintaxis de Crontab

Cron usa una sintaxis específica para definir los horarios. Consta de cinco campos, que están separados por espacios en blanco. Los campos son:

Minute Hour Day Month Day_of_the_Week

Los campos pueden tener los siguientes valores:

┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23) 
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday;
│ │ │ │ │                                       7 is also Sunday on some systems)
│ │ │ │ │
│ │ │ │ │
* * * * *  command to execute

Fuente: Wikipedia. Cron. Disponible en https://en.wikipedia.org/wiki/Cron

Cron también acepta caracteres especiales para que pueda crear horarios más complejos. Los caracteres especiales tienen los siguientes significados:

Significado del personaje

ComaPara separar varios valores
GuiónPara indicar un rango de valores
AsteriscoPara indicar todos los valores posibles
Barra inclinadaPara indicar CADA

Veamos algunos ejemplos:

  • * * * * * significa: cada minuto de cada hora de cada día del mes para cada mes para cada día de la semana.
  • 0 16 1,10,22 * * le dice a cron que ejecute una tarea a las 4 PM (que es la hora 16) los días 1, 10 y 22 de cada mes.

Instalación de Crontab

Crontab no está incluido en la instalación estándar de Python. Así, lo primero que tenemos que hacer es instalarlo.

Esto se hace con el pip mando. Lo único a considerar es que el nombre del módulo es ‘python-crontab’ y no solo ‘crontab’. El siguiente comando instalará el paquete en nuestra máquina:

$ pip install python-crontab

Obtener acceso a Crontab

Según la página de ayuda de crontab, hay cinco formas de incluir un trabajo en cron. De ellos, tres funcionan solo en Linux y dos también se pueden usar en Windows.

La primera forma de acceder a cron es usando el nombre de usuario. La sintaxis es la siguiente:

cron = CronTab(user="username")

Las otras dos formas de Linux son:

cron = CronTab()

# or

cron = CronTab(user=True)

Hay dos sintaxis más que también funcionarán en Windows.

En el primero, llamamos a una tarea definida en el archivo “filename.tab”:

cron = CronTab(tabfile="filename.tab")

En el segundo, definimos la tarea según la sintaxis de Cron:

cron = CronTab(tab="""* * * * * command""")

Crear un trabajo nuevo

Una vez que hayamos accedido a cron, podemos crear una nueva tarea usando el siguiente comando:

cron.new(command='my command')

Aquí, my command define la tarea que se ejecutará a través de la línea de comando.

También podemos agregar un comentario a nuestra tarea. La sintaxis es la siguiente:

cron.new(command='my command', comment="my comment")

Veamos esto en un ejemplo:

from crontab import CronTab

cron = CronTab(user="username")
job = cron.new(command='python example1.py')
job.minute.every(1)

cron.write()

En el código anterior, primero accedimos a cron a través del nombre de usuario y luego creamos un trabajo que consiste en ejecutar un script de Python llamado example1.py. Además, hemos configurado la tarea para que se ejecute cada 1 minuto. los write() La función agrega nuestro trabajo a cron.

El script example1.py es el siguiente:

from datetime import datetime
myFile = open('append.txt', 'a') 
myFile.write('nAccessed on ' + str(datetime.now()))

Como podemos ver en el código anterior, el programa se abrirá y agregará la frase “Accedido el” con la fecha y hora de acceso agregadas.

El resultado es el siguiente:

Figura 1

Como esperábamos, la Figura 1 muestra que el programa accedió al archivo. Continuará realizando la tarea asignada mientras el programa example1.py se esté ejecutando en cron.

Una vez que se accede a cron, podemos agregar más de un trabajo. Por ejemplo, la siguiente línea en el ejemplo anterior agregaría una segunda tarea para ser administrada por cron:

job2 = cron.new(command='python example2.py')

Una vez que se agrega una nueva tarea, podemos establecer restricciones para cada una de ellas.

Establecer restricciones

Una de las principales ventajas de usar el módulo crontab de Python es que podemos configurar restricciones de tiempo sin tener que usar la sintaxis de cron.

En el ejemplo anterior, ya hemos visto cómo configurar la ejecución del trabajo cada minuto. La sintaxis es la siguiente:

job.minute.every(minutes)

Del mismo modo, podríamos configurar las horas:

job.hour.every(hours)

También podemos configurar la tarea para que se ejecute en determinados días de la semana. Por ejemplo:

job.dow.on('SUN')

El código anterior le dirá a cron que ejecute la tarea los domingos, y el siguiente código le dirá a cron que programe la tarea los domingos y viernes:

job.dow.on('SUN', 'FRI')

De manera similar, podemos decirle a cron que ejecute la tarea en meses específicos. Por ejemplo:

job.month.during('APR', 'NOV')

Esto le dirá a cron que ejecute el programa en los meses de abril y noviembre.

Una cosa importante a considerar es que cada vez que establecemos una restricción de tiempo, anulamos la anterior. Así, por ejemplo:

job.hour.every(5)
job.hour.every(7)

El código anterior establecerá el programa final para que se ejecute cada siete horas, cancelando el programa anterior de cinco horas.

A menos que agreguemos un horario a uno anterior, como este:

job.hour.every(15)
job.hour.also.on(3)

Esto establecerá el horario cada 15 horas y a las 3 a. M.

La condición de ‘todos’ puede ser un poco confusa a veces. Si escribimos job.hour.every(15), esto será equivalente a * */15 * * *. Como vemos, el acta no se ha modificado.

Si queremos poner el campo de minutos a cero, podemos usar la siguiente sintaxis:

job.every(15).hours()

Esto establecerá el horario en 0 */4 * * *. De manera similar para los campos ‘día del mes’, ‘mes’ y ‘día de la semana’.

Ejemplos:

  • job.every(2).month es equivalente a 0 0 0 */2 * y job.month.every(2) es equivalente a * * * */2 *
  • job.every(2).dows es equivalente a 0 0 * * */2 y job.dows.every(2) es equivalente a * * * * */2

Podemos ver las diferencias en el siguiente ejemplo:

from crontab import CronTab

cron = CronTab(user="username")

job1 = cron.new(command='python example1.py')

job1.hour.every(2)

job2 = cron.new(command='python example1.py')
job2.every(2).hours()

for item in cron:
    print item

cron.write()

Después de ejecutar el programa, el resultado es el siguiente:

$ python cron2.py
* */2 * * * python /home/eca/cron/example1.py
0 */2 * * * python /home/eca/cron/example1.py
$

Figura 2

Como podemos ver en la Figura 2, el programa ha establecido los minutos de la segunda tarea en cero y ha definido los minutos de la primera tarea en su valor predeterminado.

Finalmente, podemos configurar la tarea para que se ejecute cada vez que arrancamos nuestra máquina. La sintaxis es la siguiente:

job.every_reboot()

Restricciones de compensación

Podemos borrar todas las restricciones de la tarea con el siguiente comando:

job.clear()

El siguiente código muestra cómo utilizar el comando anterior:

from crontab import CronTab

cron = CronTab(user="username")

job = cron.new(command='python example1.py', comment="comment")
job.minute.every(5)

for item in cron:
    print item

job.clear()

for item in cron:
    print item
cron.write()

Después de ejecutar el código obtenemos el siguiente resultado:

$ python cron3.py
*/5 * * * * python /home/eca/cron/example1.py # comment
* * * * * python /home/eca/cron/example1.py # comment

figura 3

Como podemos ver en la Figura 3, el horario ha cambiado de cada 5 minutos a la configuración predeterminada.

Habilitación y deshabilitación de un trabajo

Una tarea se puede habilitar o deshabilitar usando los siguientes comandos:

Para habilitar un trabajo:

job.enable()

Para deshabilitar un trabajo:

job.enable(False)

Para verificar si una tarea está habilitada o deshabilitada, podemos usar el siguiente comando:

job.is_enabled()

El siguiente ejemplo muestra cómo habilitar y deshabilitar un trabajo creado previamente y verificar ambos estados:

from crontab import CronTab

cron = CronTab(user="username")

job = cron.new(command='python example1.py', comment="comment")
job.minute.every(1)

cron.write()

print job.enable()
print job.enable(False)

El resultado es el siguiente:

$ python cron4.py
True
False

Figura 4

Comprobación de validez

Podemos comprobar fácilmente si una tarea es válida o no con el siguiente comando:

job.is_valid()

El siguiente ejemplo muestra cómo utilizar este comando:

from crontab import CronTab

cron = CronTab(user="username")

job = cron.new(command='python example1.py', comment="comment")
job.minute.every(1)

cron.write()

print job.is_valid()

Luego de ejecutar el programa anterior, obtenemos la validación, como se ve en la siguiente figura:

$ python cron5.py
True

Figura 5

Listado de todos los trabajos de Cron

Todos los trabajos cron, incluidos los trabajos deshabilitados, se pueden enumerar con el siguiente código:

for job in cron:
    print job

Agregar esas líneas de código a nuestro primer ejemplo mostrará nuestra tarea imprimiendo en la pantalla lo siguiente:

$ python cron6.py
* * * * * python /home/eca/cron/example1.py

Figura 6

Buscando trabajo

El módulo crontab de Python también nos permite buscar tareas en función de un criterio de selección, que puede basarse en un comando, un comentario o una hora programada. Las sintaxis son diferentes para cada caso.

Encuentra según el comando:

cron.find_command("command name")

Aquí, ‘nombre de comando’ puede ser una subcoincidencia o una expresión regular.

Encuentra según comentario:

cron.find_comment("comment")

Encuentra según el tiempo:

cron.find_time(time schedule)

El siguiente ejemplo muestra cómo encontrar una tarea previamente definida, según los tres criterios mencionados anteriormente:

from crontab import CronTab

cron = CronTab(user="username")

job = cron.new(command='python example1.py', comment="comment")
job.minute.every(1)

cron.write()

iter1 = cron.find_command('exam')
iter2 = cron.find_comment('comment')
iter3 = cron.find_time("*/1 * * * *")

for item1 in iter1:
    print item1

for item2 in iter2:
    print item2

for item3 in iter3:
    print item3

El resultado es la lista del mismo trabajo tres veces:

$ python cron7.py
* * * * * python /home/eca/cron/example1.py # comment
* * * * * python /home/eca/cron/example1.py # comment
* * * * * python /home/eca/cron/example1.py # comment

Figura 7

Como puede ver, encuentra correctamente el comando cron cada vez.

Eliminar trabajos

Cada trabajo se puede eliminar por separado. La sintaxis es la siguiente:

cron.remove(job)

El siguiente código muestra cómo eliminar una tarea que se creó anteriormente. El programa primero crea la tarea. Luego, enumera todas las tareas, mostrando la que acaba de crear. Después de esto, elimina la tarea y muestra la lista vacía resultante.

from crontab import CronTab

cron = CronTab(user="username")

job = cron.new(command='python example1.py')
job.minute.every(1)

cron.write()
print "Job created"

# list all cron jobs (including disabled ones)
for job in cron:
    print job

cron.remove(job)
print "Job removed"

# list all cron jobs (including disabled ones)
for job in cron:
    print job

El resultado es el siguiente:

$ python cron8.py
Job created
* * * * * python /home/eca/cron/example1.py
Job removed

Figura 8

Los trabajos también se pueden eliminar en función de una condición. Por ejemplo:

cron.remove_all(comment="my comment")

Esto eliminará todos los trabajos donde comment="my comment".

Borrar todos los trabajos

Todos los trabajos cron se pueden eliminar a la vez mediante el siguiente comando:

cron.remove_all()

El siguiente ejemplo eliminará todos los trabajos cron y mostrará una lista vacía.

from crontab import CronTab

cron = CronTab(user="username")
cron.remove_all()

# list all cron jobs (including disabled ones)
for job in cron:
    print job

Variables ambientales

También podemos definir variables ambientales específicas para nuestra tarea programada y mostrarlas en la pantalla. Las variables se guardan en un diccionario. La sintaxis para definir una nueva variable de entorno es la siguiente:

job.env['VARIABLE_NAME'] = 'Value'

Si queremos obtener los valores de todas las variables ambientales, podemos usar la siguiente sintaxis:

job.env

El siguiente ejemplo define dos nuevas variables ambientales para la tarea ‘usuario’ y muestra su valor en la pantalla. El código es el siguiente:

from crontab import CronTab

cron = CronTab(user="username")

job = cron.new(command='python example1.py')
job.minute.every(1)
job.env['MY_ENV1'] = 'A'
job.env['MY_ENV2'] = 'B'

cron.write()

print job.env

Después de ejecutar el programa anterior, obtenemos el siguiente resultado:

$ python cron9.py
MY_ENV1=A
MY_ENV2=B

Figura 9

Además, las variables de entorno de nivel cron se almacenan en ‘cron.env’.

Terminando

El módulo de Python crontab nos proporciona una herramienta útil para administrar mediante programación nuestra aplicación cron, que está disponible para sistemas similares a Unix. Al usarlo, en lugar de tener que depender de la creación de crontabs, podemos usar el código Python para administrar tareas frecuentes.

El módulo es bastante completo. Aunque ha habido algunas críticas sobre su comportamiento, contiene funciones para conectarse a cron, crear tareas programadas y administrarlas. Como se muestra en los ejemplos anteriores, su uso es bastante directo. Así, proporciona una herramienta que permite scripts complejos con la principal característica de Python: simplicidad.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad