Мастер времени: как управлять задачами в asyncio с помощью call_soon и call_later
Мастер времени: как управлять задачами в asyncio с помощью call_soon и call_later
Привет, друг! Если ты когда-либо пытался одновременно варить кофе, гладить кота и отвечать на сообщения в чате — поздравляю, ты уже сталкивался с необходимостью асинхронного планирования задач! Сегодня мы разберём, как стать виртуозом управления временем в Python при помощи двух волшебных инструментов: call_soon и call_later из модуля asyncio.
Кратко о главном: цикл событий — это ваш личный дирижёр
Представьте, что ваш код — это оркестр. Без дирижёра (цикла событий) скрипки будут спорить с барабанами, а трубы перекрикивать друг друга. Asyncio аккуратно разводит их по партиям, говоря: “Сейчас ты, потом ты, а ты пока подожди, но не засыпай!“.
import asyncio
async def main():
loop = asyncio.get_event_loop()
# Здесь мы будем творить магию!
asyncio.run(main())
call_soon: “Сделай это сейчас, но дай мне закончить чай!”
Теория с примерами из жизни
loop.call_soon() — это как попросить друга: “Эй, передай соль, но только после того, как дочитаешь этот мем”. Задача ставится в очередь и выполнится сразу, как цикл событий закончит текущее дело.
Пример из кулинарии: Вы — повар, который:
- Ставит воду кипятиться (
call_soon). - Нарезает овощи (текущая задача).
- Как только вода закипит (срабатывает колбэк), бросает пасту.
def add_pasta():
print("🍝 Паста отправилась в танец кипятка!")
async def cook():
loop = asyncio.get_event_loop()
print("🔥 Ставим воду на огонь")
loop.call_soon(add_pasta) # Не блокируем нарезку овощей!
await asyncio.sleep(1) # Имитируем нарезку
print("🥕 Овощи готовы к салату!")
asyncio.run(cook())
Вывод:
🔥 Ставим воду на огонь
🍝 Паста отправилась в танец кипятка!
🥕 Овощи готовы к салату!
А вот и шутка:
Почему call_soon не используют в ресторанах быстрого питания?
Потому что он сразу кричит “Заказ готов!”, даже если клиент ещё не успел сесть!
call_later: “Напомни мне через 5 минут… если не забудешь”
Теория с щепоткой юмора
loop.call_later(5, callback) — это цифровой аналог фразы “Я точно начну бегать… с понедельника”. Задача выполнится через N секунд, но цикл событий продолжит работать без простоев.
Пример из жизни:
Вы ставите пирог в духовку и:
- Устанавливаете таймер на 30 минут (
call_later). - Смотрите сериал (текущая задача).
- По сигналу таймера (колбэк) проверяете пирог.
def check_pie():
print("🎂 Время спасать пирог от пригорания!")
async def bake():
loop = asyncio.get_event_loop()
print("🔥 Пирог в духовке! Таймер на 3 секунды...")
loop.call_later(3, check_pie) # Через 3 секунды сработает
await asyncio.sleep(5) # Сериал "Кремниевая долина"
print("📺 Серия закончилась. Что с пирогом?")
asyncio.run(bake())
Вывод:
🔥 Пирог в духовке! Таймер на 3 секунды...
🎂 Время спасать пирог от пригорания!
📺 Серия закончилась. Что с пирогом?
Шутка в тему:
call_later — любимый инструмент котов.
”Напомни хозяину дать мне корм через час…
(через час)
МЯУ! Ты это заслужил!”
Бонус: Как отменить напоминание о совещании
Каждый Handle (объект, возвращаемый call_soon/call_later) можно отменить, как неловкое сообщение в Telegram.
async def cancel_demo():
loop = asyncio.get_event_loop()
def remind():
print("Напоминание: пора на совещание!")
print("⏰ Установлено напоминание на через 2 секунды")
handle = loop.call_later(2, remind)
await asyncio.sleep(1)
print("😱 Вспомнил, что совещание перенесли!")
handle.cancel() # Фух, пронесло!
await asyncio.sleep(2)
print("🎉 Никаких совещаний!")
asyncio.run(cancel_demo())
Реальный пример: веб-сервер с логированием
Представьте сервер, который:
- Сразу отвечает клиенту (
call_soon) - Через 5 секунд пишет в лог (
call_later)
def log_request():
print("📝 Лог: пользователь X получил данные")
async def handle_request():
loop = asyncio.get_event_loop()
print("🖥 Отправляем ответ клиенту...")
loop.call_soon(lambda: print("⚡ Данные отправлены!"))
loop.call_later(5, log_request)
asyncio.run(handle_request())
Заключение: вы теперь хрономастер!
- call_soon — “сделай, когда освободишься, но не откладывай”.
- call_later — “напомни мне, если не увлечёшься мемами”.
Как говаривал древний философ:
“Хороший разработчик не тот, кто успевает всё, а тот, чей event loop не падает с ошибкой ‘Task was destroyed but it is pending!’”.
Теперь вы можете смело планировать задачи, как шеф-повар на кухне стартапа — одновременно, эффективно, и с возможностью отменить подгорающий тост. Удачи в асинхронных подвигах! 🚀