Ответ
Celery — это распределенная очередь задач для Python. Её основная цель — выполнение длительных или ресурсоемких операций асинхронно, чтобы не блокировать основной поток приложения (например, веб-сервера).
Основные сценарии использования:
- Отправка email или push-уведомлений.
- Обработка изображений или видео (создание превью, конвертация).
- Выполнение периодических задач по расписанию (Celery Beat).
- Взаимодействие с медленными внешними API.
Пример: Запуск простой задачи сложения
1. Установка зависимостей
В качестве брокера сообщений будем использовать Redis.
pip install celery redis
2. Определение задачи (tasks.py)
from celery import Celery
import time
# Инициализация Celery с указанием имени приложения и URL брокера
app = Celery('tasks', broker='redis://localhost:6379/0')
@app.task
def add(x, y):
"""Простая задача, которая складывает два числа."""
time.sleep(5) # Имитация долгой операции
return x + y
3. Запуск worker'а
Worker — это процесс, который слушает очередь и выполняет задачи по мере их поступления. Запускается из терминала:
celery -A tasks worker --loglevel=info
4. Вызов задачи из другого скрипта
from tasks import add
# .delay() ставит задачу в очередь и немедленно возвращает объект AsyncResult
result = add.delay(4, 6)
print(f"Задача {result.id} отправлена в очередь.")
# Чтобы дождаться и получить результат (блокирующая операция):
# final_result = result.get(timeout=10)
# print(f"Результат: {final_result}")
Ключевые компоненты:
- Task: Функция, декорированная
@app.task. - Broker (Брокер): Посредник (Redis, RabbitMQ), который хранит задачи в очереди.
- Worker (Воркер): Процесс, который забирает задачи из очереди и выполняет их.
- Backend (Бэкенд): Опциональное хранилище для результатов выполнения задач.
Ответ 18+ 🔞
А, Celery! Ну это ж классика, блядь, для тех, кто не хочет, чтобы его веб-сервер впадал в кому, пока там какая-то ебучка с картинками или письмами возится. Короче, распределённая очередь задач, чтобы всё тяжёлое и долгое выкинуть куда подальше, в асинхрон, и не париться.
Зачем это, собственно, нужно?
Ну, представь: пользователь нажал кнопку «загрузить видео», а твой сервер вместо того, чтобы сказать «ок, принял» и отдать ответ, начинает его конвертить на месте. Пока он там пыхтит, все остальные пользователи стоят в очереди и думают: «Ну что, сука, зависло?». Вот чтобы такого не было, и нужна эта штука. Отправил задачу в очередь — и свободен. А там уж воркеры, эти безмозглые трудяги, потихоньку всё порешают.
Где применяют?
- Письма слать. Чтобы не ждать, пока почтовый сервер ответит «ок».
- Картинки/видео обрабатывать. Создание превьюшек, сжатие — та ещё долбанутая история по времени.
- По расписанию что-то делать. Типа каждую ночь отчёты генерить. Есть для этого отдельный модуль — Celery Beat.
- Сторонние API дергать. Которые могут отвечать по пять минут, а то и вовсе лежать.
Пример: Сложить два числа, но с понтами и задержкой
1. Ставим всё нужное Брокером пусть будет Redis, проще пареной репы.
pip install celery redis
2. Пишем саму задачу (tasks.py)
Вот тут, смотри, магия начинается.
from celery import Celery
import time
# Создаём приложение. Говорим, как его звать и где брокер (очередь) живёт.
app = Celery('tasks', broker='redis://localhost:6379/0')
@app.task # Вот этот декоратор — волшебный пендель. Он делает из функции задачу для очереди.
def add(x, y):
"""Задача, которая складывает два числа, но прикидывается, что это овердохуища сложно."""
time.sleep(5) # Симуляция, будто мы там супер-сложные вычисления проводим, а на деле просто спим, блядь.
return x + y
3. Запускаем воркера Это такой отдельный процесс, который будет слушать очередь и выполнять задачи. Как раб на галерах, только в терминале.
celery -A tasks worker --loglevel=info
4. Вызываем задачу из другого места Допустим, из твоего основного Flask/Django приложения.
from tasks import add
# .delay() — это как крикнуть в коридор: «Эй, кто-нибудь, сложи 4 и 6!». Задача улетает в очередь.
result = add.delay(4, 6)
print(f"Задача с ID {result.id} отправлена. Сиди, жди, не еби мозг.")
# Если очень надо дождаться результата прямо щас (но это уже блокирует поток):
# final_result = result.get(timeout=10)
# print(f"Результат: {final_result}") # Спойлер: будет 10, ёпта.
Из чего всё это, блядь, состоит?
- Задача (Task): Обычная функция, но в майке-декораторе
@app.task. Её можно швырнуть в очередь. - Брокер (Broker): Это посредник, почтовый ящик. Redis или RabbitMQ. В него задачи кидают, а воркеры из него забирают.
- Воркер (Worker): Отдельный процесс-зек, который пашет на шахте (очереди) и выполняет задачи. Может быть их овердохуища.
- Бэкенд (Backend): Необязательная, но полезная хуйня. Хранилище, куда складывают результаты выполнения задач, чтобы потом их можно было проверить. А то отправил задачу и нихуя не понял — выполнилась или нет.
Вот и вся философия. Отправил тяжёлую работу на сторону — и живешь спокойно, пока воркеры там всё проебывают. Главное, чтобы брокер не лег, а то вся система, как та Муму, на дно пойдёт.