Как выполнять асинхронные функции циклично каждые 30 минут, час?

Рейтинг: 1Ответов: 2Опубликовано: 18.07.2023

У меня есть телеграмм бот, мне нужно чтобы о каждые 2 минуты проверял базу данных В этой базе хранится список заявок бронирования, у каждой заявки есть время на которое пользователь забронировал что-либо, нужно чтобы бот сверял время и по истечению времени(чтобы заявка не была просроченной) удалял ее автоматически и присылал пользователю уведомление о том что его заявка истекла

За это отвечает функция

await check_requests()

Не await я не могу сделать так как в процессе своей работы она отправляет сообщения пользователю(а эта функция( await bot.send_message() ) всегда асихронна
я пользуюсь вот таким таймером:

async def checking():
     threading.Timer(60, await check_requests()).start()

и я хочу вызывать функцию в моей основной функции, чтобы это выглядело как-то вот так:

if __name__ == "__main__":
     await checking()
     executor.start_polling(dispatcher, skip_updates=True)

как мне это сделать? Или лучше как-то по-другому реализовать ее работу? На данный момент я включаю работу этой функции при вводе команды /start Вот таким образом:

await checking()

и мне выдает такую ошибку:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Users\Serg\AppData\Local\Programs\Python\Python311\Lib\threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "C:\Users\Serg\AppData\Local\Programs\Python\Python311\Lib\threading.py", line 1394, in run
    self.function(*self.args, **self.kwargs)
TypeError: 'NoneType' object is not callable

Ответы

▲ 2Принят

threading.Timer - сразу нет. заменяется на loop.call_later

await внутри Timer тоже выполняется сразу, нужна лямбда, но асинхронных лямбд не бывает. разве что create_task там вставлять.

Но проще

async def sheduler(period, fu,  *args, **kw):
    while True:
        await asyncio.sleep(period)
        await fu( *args, **kw)

loop = asyncio.new_event_loop() #или asyncio.get_event_loop() если уже есть запущенный луп.

task = loop.create_task(sheduler(60*60, check_requests))

loop.run_forever() # или основной луп бота.
▲ 0

Проблему смог решить, но заработало только, когда переделал чуть по-другому

Вместо:

loop = asyncio.new_event_loop()  
task = loop.create_task(sheduler(60*60, check_requests))

Сделал:

loop = asyncio.get_event_loop()
loop.create_task(sheduler(60*60, check_requests))