Así que hoy hablaré de una alternativa de Celery llamada Huey , que viene con una configuración mucho más fácil que Celery y es mucho más pequeña en comparación con Celery.
La razón por la que decidí probar Huey es porque a veces he tenido algunos problemas con Celery al realizar algunas tareas comunes porque la documentación no es muy buena.
Para aquellos que no saben qué es Celery o no lo han usado antes, Huey es una cola de tareas asíncrona que permite realizar tareas programadas o de larga duración en segundo plano.
Instalaremos los siguientes paquetes:
El siguiente blog viene acompañado de un repositorio de GitHub que puede utilizar para probar el proyecto de demostración que crearemos.
Haga clic aquí para ver el repositorio.
Abra la terminal y escriba lo siguiente para crear un directorio; Puedes omitir este paso y hacerlo desde el propio Explorador de archivos.
mkdir huey_demo
Primero creemos un virtualenv para instalar las dependencias de nuestro proyecto:
python -m venv venv
Active el virtualenv (Linux):
source venv/bin/activate
Escriba el siguiente comando en la terminal para instalar todas las dependencias:
pip install Django==4.0.4 redis==4.2.2 huey==2.4.3
Al momento de escribir este artículo, estas eran las versiones con las que probé esta configuración; esté atento al repositorio de Github para conocer cualquier actualización de la última versión en el futuro.
Cree el proyecto Django escribiendo el siguiente comando en la terminal:
django-admin startproject django_huey_demo
Cambie el directorio al directorio del proyecto Django:
cd django_huey_demo
Crea la aplicación bajo nuestro proyecto:
python manage.py startapp demo
Incluya la aplicación creada en el proyecto settings.py
, realice los siguientes cambios:
INSTALLED_APPS = [ # Existing Apps "demo.apps.DemoConfig", # <== Add this line ]
Establezca el modo de depuración en False
en settings.py
:
DEBUG=False
Estamos configurando Debug en False para que podamos ver cómo se ejecuta Huey en producción; hablaremos más sobre esto más adelante.
Ahora que hemos terminado de configurar nuestro proyecto, es un buen momento para explicarle lo que construiremos hoy.
Obtendremos la "Palabra del día" diariamente desde la API de Wordnik . Luego almacenaremos la palabra, su definición y un ejemplo de la palabra en una oración en nuestra base de datos.
Configuraremos una tarea periódica usando Huey que buscará la Palabra del día y la almacenará.
Para almacenar la palabra crearemos un modelo Django de la misma.
Puede seguir esta guía para obtener la clave API.
Necesitamos agregar Huey a las aplicaciones instaladas de nuestro proyecto, así que realice los siguientes cambios en el archivo settings.py
:
INSTALLED_APPS = [ # Existing apps 'huey.contrib.djhuey', # <== Add this line ]
Necesitamos instalar Redis para Huey para almacenar información sobre las tareas en cola como solíamos hacer con Celery también. Puede consultar el siguiente enlace para instalar Redis según su sistema operativo específico.
Si se siente cómodo usando Docker, puede usar el siguiente comando:
docker run --name redis_huey -p 6379:6379 -d redis
De forma predeterminada, Huey intentará conectarse al servidor Redis que se ejecuta en localhost:6379
. Si no está presente, generará un error.
Agregue el siguiente código a su archivo demo/models.py
:
from django.db import models class Word(models.Model): word = models.CharField(max_length=200) part_of_speech = models.CharField(max_length=100) definition = models.TextField() example = models.TextField() def __str__(self): return self.word
Realizar migraciones:
python manage.py makemigrations demo
Aplicar migraciones:
python manage.py migrate demo
Cree un archivo llamado tasks.py
en el directorio de la aplicación de demostración. La razón por la que nombramos nuestro archivo tasks.py
es para ayudar a Huey a descubrir automáticamente las tareas presentes en nuestras aplicaciones registradas; si le pusiéramos a nuestro archivo un nombre distinto a ese, tendríamos que registrar nuestra tarea manualmente. Si desea saber más, puede consultar la documentación de Huey aquí .
Antes de escribir la definición de la tarea, necesitamos instalar requests
de dependencia adicionales. Instálalo escribiendo lo siguiente en tu terminal:
pip install requests==2.27.1
Ahora viene el código:
import requests from django.conf import settings from huey import crontab from huey.contrib.djhuey import db_periodic_task from demo.models import Word @db_periodic_task(crontab(hour="18", minute="00")) def fetch_daily_word(): r = requests.get( f"https://api.wordnik.com/v4/words.json/wordOfTheDay?api_key={settings.WORDNIK_API_KEY}") data = r.json() Word.objects.get_or_create( word=data["word"], part_of_speech=data["definitions"][0]["partOfSpeech"], definition=data["definitions"][0]["text"], example=data["examples"][0]["text"] )
Agregue la siguiente línea en la configuración de su proyecto:
WORDNIK_API_KEY = "api-key-here"
Este bloque de código puede ser mucho para asimilar, así que repasemos los elementos que contiene uno por uno:
Decorador Huey
from huey.contrib.djhuey import db_periodic_task
Este es un decorador proporcionado por Huey para registrar tareas periódicas que implican trabajar con la base de datos. Este decorador cierra automáticamente la conexión de la base de datos al finalizar la tarea. Para obtener más detalles, puede consultar aquí.
Programación de crontab
@db_periodic_task(crontab(hour="18", minute="00"))
Estamos pasando el argumento crontab(hour="18", minute="00")
a nuestro decorador de tareas periódicas, esto le dice a Huey que ejecute nuestra tarea a las 6 p.m. todos los días. Puede utilizar este sitio web para crear sus programaciones crontab, yo lo uso siempre.
Clave API de Wordnik
from django.conf import settings # Usage ## settings.WORDNIK_API_KEY
from django.conf import settings
es la forma estándar de importar cualquier dato desde la configuración de nuestro proyecto, es útil en casos donde tenemos múltiples archivos de configuración configurados para diferentes entornos para que sepa qué archivo elegir sin que tengamos que preocuparnos. él. Descubre qué archivo de configuración estamos usando desde la variable de entorno DJANGO_SETTINGS_MODULE
. Pero no tienes que preocuparte por estos detalles.
Luego usamos la clave en nuestra llamada a la API de Wordnik.
Llamada API de Wordnik
r = requests.get( f"https://api.wordnik.com/v4/words.json/wordOfTheDay?api_key={settings.WORDNIK_API_KEY}")
Aquí, utilizamos el módulo de solicitudes para realizar una solicitud GET a la API de Wordnik mientras pasamos nuestra clave API para la autenticación.
Almacenamiento de palabras en la base de datos.
data = r.json() Word.objects.get_or_create( word=data["word"], part_of_speech=data["definitions"][0]["partOfSpeech"], definition=data["definitions"][0]["text"], example=data["examples"][0]["text"] )
Después de analizar la respuesta de la API, almacenamos la definición de la palabra en nuestra base de datos. Estamos utilizando el método get_or_create
en lugar del método create
aquí para no crear múltiples copias de la misma palabra en nuestra base de datos si la API de Wordnik alguna vez repite esa palabra.
Respuesta de la API de Wordnik
Así es como se ve la respuesta de la API de Wordnik para el punto final de la Palabra del día. Algunas de las secciones irrelevantes de la respuesta se han truncado por motivos de brevedad.
{ "word": "stolon", "definitions": [ { "source": "ahd-5", "text": "A long thin stem that usually grows horizontally along the ground and produces roots and shoots at widely spaced nodes, as in a strawberry plant.", "note": null, "partOfSpeech": "noun" }, // More definitions here... ], "publishDate": "2022-05-08T03:00:00.000Z", "examples": [ { "title": "4.1 Nursery establishment", "text": "A stolon is a stem that grows along the ground, producing at its nodes new plants with roots and upright stems.", // Additional data here... }, // More examples here... ], // Additional fields here... }
Puede iniciar el trabajador Huey escribiendo el siguiente comando en su terminal:
python manage.py run_huey
Puede pasar varios indicadores al comando anterior que cambiará lo que se registra en la consola, como por ejemplo:
-v, --verbose
: registro detallado (incluye nivel DEBUG)-q, --quiet
- registro mínimo-S, --simple
- formato de registro simple (“mensaje de hora”)
Para ver otras opciones de inicio de sesión, consulte los documentos aquí .
Huey viene con múltiples decoradores de tareas dependiendo de las operaciones que esté realizando dentro de la tarea.
Explicaré brevemente qué hacen todos ellos a continuación.
Aquí está la declaración de importación para todos los decoradores:
from huey.contrib.djhuey import task, periodic_task, db_task, db_periodic_task
task
: Una tarea regular.periodic_task
: cuando desea ejecutar una tarea periódicamente según un cronograma.db_task
: cuando desea realizar operaciones de base de datos dentro de su tarea.db_periodic_task
: cuando desea realizar operaciones de base de datos en una tarea periódica.Déjame mostrarte algunos ejemplos más de cómo puedes usar crontab para programar tus tareas.
crontab(minute='*/3')
programaría la tarea para que se ejecute cada tres minutos.crontab(hour='*/3', minute='5')
crearía una tarea que se ejecutará cada tres horas 5 minutos después.crontab(minute='00', hour='10', month='*/2', day_of_week='*/5')
crearía una tarea que se ejecutaría cada cinco días de la semana, de cada segundo mes a las 10:00 A.M. Por ejemplo, tienes la siguiente tarea definida dentro de tasks.py
:
from huey.contrib.djhuey import task @task() def count(): for i in range(10): print(i)
Ahora, si desea llamar a esta tarea pero desea que se ejecute después de 5 segundos, puede hacer lo siguiente:
count.schedule(delay=5)
El parámetro delay
toma valores en segundos, por lo que si desea que se ejecute después de 5 minutos, especifique 300 segundos.
Supongamos que agrega la siguiente lógica a nuestra tarea existente:
@db_periodic_task(crontab(hour="18", minute="00"), retries=2) def fetch_daily_word(): r = requests.get( f"https://api.wordnik.com/v4/words.json/wordOfTheDay?api_key={settings.WORDNIK_API_KEY}") if r.status_code != 200: raise Exception("Unable to fetch data from Wordnik API") ## Add this logic else: data = r.json() Word.objects.get_or_create( word=data["word"], part_of_speech=data["definitions"][0]["partOfSpeech"], definition=data["definitions"][0]["text"], example=data["examples"][0]["text"] )
Entonces, agregamos la lógica para verificar el código de estado de la respuesta y, si es distinto de 200, reintentará esa tarea hasta 2 veces. Pero estos reintentos se producirían sin ningún intervalo de tiempo entre los dos intentos. Ahora bien, ¿qué sucede si desea retrasar varios intentos de esta tarea? Podemos hacerlo pasando el argumento retry_delay
, acepta valores en segundos.
@db_periodic_task(crontab(hour="18", minute="00"), retries=2, retry_delay=10)
Esto provocará un retraso de 10 segundos entre múltiples intentos.
Huey viene con una configuración predeterminada que facilita el trabajo con Huey durante el desarrollo en Django. Entonces, siempre que tenga DEBUG=True
presente en su archivo settings.py
, las tareas se ejecutarán sincrónicamente como las llamadas a funciones normales. El propósito de esto es evitar ejecutar Redis y un proceso de consumidor adicional mientras se desarrollan o ejecutan pruebas. Puedes leer más sobre esto aquí .
Para esto, necesitamos agregar la siguiente línea en settings.py
:
HUEY = {}
Sin embargo, si desea anular este comportamiento, puede agregar la siguiente configuración de Huey:
HUEY = { "immediate": False }
Si tiene la configuración anterior mencionada en settings.py
, mientras tiene DEBUG=True
, Huey le pedirá que configure Redis y ejecute Huey Worker usando el comando run_huey
.
Algunas observaciones sobre Huey en comparación con Apio son:
run_huey
.