Celery
Celery — это асинхронная распределенная очередь задач на Python, предназначенная для выполнения фоновых задач, не загружая основной поток приложения.
Установка:
"pip install celery"
Создадим экземпляр Celery в файле "learn_redis.py":
from celery import Celery
REDIS_URL="rediss://***************ray-168337.upstash.io:6379?ssl_cert_reqs=CERT_NONE"
Я использовал онлайн Redis — сайт Upstash.com
Основные возможности Celery
Фоновая задача определяется при помощи декоратора "@app.task()":
@app.task()
def add_num(x, y):
return x + y
Если результат не нужен:
@app.task(ignore_result=True)
def add_num(x, y):
return x + y
Ограничение скорости выполнения:
@app.task(rate_limit='10/m')
def add(x, y):
return x + y
Retry
Задача может завершиться ошибкой из-за временных проблем. Можно настроить автоматическое перевыполнение через некоторое время
@app.task(bind=True, max_retries=3, default_retry_delay=60)
def add(self, x, y):
try:
return x + y
except SomeTemporaryException as exc:
raise self.retry(exc=exc)
Здесь задача повторится до 3 раз с интервалом 60 секунд.
Вызов задач
"delay()" — простой способ вызвать задачу асинхронно:
res = add_num.delay(5, 3)
print(res.get())
"apply_async()" даёт больше возможностей, например можно указать задержку, приоритет, callback и errback:
result = add.apply_async((4, 4), countdown=10)
Задача выполнится через 10 секунд
"signature()" создаёт подпись задачи:
from celery import signature
sig = signature('tasks.add', args=(2, 2), immutable=True)
sig.delay()
"chain()" соединяет задачи в последовательность, где результат одной передаётся следующей:
from celery import chain
# (4 + 4) -> (8 * 10)
res = chain(add.s(4, 4), multiply.s(10))()
"group()" выполняет несколько задач параллельно:
from celery import group
# выполняет add(2, 2) и add(4, 4) параллельно
group_result = group(add.s(2, 2), add.s(4, 4))()
"chord()" объединяет "group()" и "chain()": сначала задачи выполняются параллельно, затем их результаты передаются callback-задаче:
from celery import chord
# cначала выполняет add(2, 2) и add(4, 4) параллельно, затем результаты передаются в multiply()
result = chord([add.s(2, 2), add.s(4, 4)])(multiply.s(2))
Практика
Устанавливаем необходимые библиотеки:
"pip install celery, redis, celery[redis]"
В файле "learn_redis.py" подключаем Redis и создаём приложение:
from celery import Celery
REDIS_URL = ***************ray-168337.upstash.io:6379?ssl_cert_reqs=CERT_NONE"
app = Celery(
'example',
broker=REDIS_URL,
backend=REDIS_URL
)
@app.task()
def add_num(x, y):
return x + y
Создаём "run_task_celery_redis.py" и вызываем задачу:
res = add_num.delay(5, 3)
print(res.get())
Запускаем Celery:
celery -A learn_redis worker --loglevel=info --pool=solo
После запуска Celery выполняем в файле (runc_task_celery_redis.py)
python run_task_celery_redis.py
После этого задача должна выполниться.
❗❗ Версии Celery начиная с 4.x.x не работают на Windows. Для запуска новой версии Celery на Windows используйте флаг "--pool=solo". ❗❗