I am coding telegram-bot, using Flask and asyncio. And I have a function for receiving and processing requests - get_messages()
. And test function - sleep_func()
, which will sleep for a while(20 seconds), but get_messages()
will be working at this moment, when sleep_func()
is sleeping. After 20 seconds sleep_func()
must wake up, print some text, but doesn't finish the get_messages()
. So, I want to implement asynchrony. I tried to do this, using asyncio.create_task
, that worked, but only for one request(see at the comments in get_messages()
). Now I tried another way, but it gives me this error:
ERROR:asyncio:Task exception was never retrieved
future: <Task finished name='Task-7' coro=<get_messages() done, defined at D:\Python_Labs\FilmMarketBot\fm_bot.py:31> exception=RuntimeError('Timeout context manager should be used inside a task')>
Traceback (most recent call last):
File "D:\Python_Labs\FilmMarketBot\fm_bot.py", line 37, in get_messages
await message(bot)
File "D:\Python_Labs\FilmMarketBot\bot_files\message_handling.py", line 14, in message
await commands(bot, chat_id)
File "D:\Python_Labs\FilmMarketBot\bot_files\messages\bot_commands\commands.py", line 11, in commands
await start(bot, chat_id)
File "D:\Python_Labs\FilmMarketBot\bot_files\messages\bot_commands\commands_methods.py", line 11, in start
await bot.send_message(chat_id, f"Hello, {first_name}!")
File "D:\Python_Labs\FM_Bot_test\venv\lib\site-packages\aiogram\bot\bot.py", line 339, in send_message
result = await self.request(api.Methods.SEND_MESSAGE, payload)
File "D:\Python_Labs\FM_Bot_test\venv\lib\site-packages\aiogram\bot\base.py", line 231, in request
return await api.make_request(await self.get_session(), self.server, self.__token, method, data, files,
File "D:\Python_Labs\FM_Bot_test\venv\lib\site-packages\aiogram\bot\api.py", line 139, in make_request
async with session.post(url, data=req, **kwargs) as response:
File "D:\Python_Labs\FM_Bot_test\venv\lib\site-packages\aiohttp\client.py", line 1138, in __aenter__
self._resp = await self._coro
File "D:\Python_Labs\FM_Bot_test\venv\lib\site-packages\aiohttp\client.py", line 466, in _request
with timer:
File "D:\Python_Labs\FM_Bot_test\venv\lib\site-packages\aiohttp\helpers.py", line 701, in __enter__
raise RuntimeError(
RuntimeError: Timeout context manager should be used inside a task
This is my fm_bot.py:
# бібліотека request для отримання запитів(повідомлень), які надходять на Flask-сервер від Телеграм-серверу і Stripe
from flask import Flask, request
import logging
from aiogram import Bot, Dispatcher
from threading import Thread
# from dotenv import load_dotenv
from time import sleep
import asyncio
import time
from bot_files.models import db, Users, Films, Purchases
from bot_files.message_handling import message, callback_query, object, other_messages
# from bot_files.other import technical_works
from bot_files.chat_member import delete_user
from bot_files.stripe import create_stripe_webhook
from bot_files.objects.stripe_requests_files.purchases import add_purchase
from bot_files.config import *
logging.basicConfig(level=logging.INFO)
bot = Bot(token=bot_token)
dp = Dispatcher(bot)
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = db_url
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
db.init_app(app)
async def get_messages():
print("Flag")
print(request.json)
message_type = list(request.json.keys())[1]
if message_type == 'message':
await message(bot)
elif message_type == 'callback_query':
await callback_query(bot, payment_token, stripe_token)
elif message_type == 'my_chat_member':
chat_id = request.json["my_chat_member"]["chat"]["id"]
if request.json["my_chat_member"]["new_chat_member"]["status"] == "kicked":
await delete_user(chat_id)
elif message_type == 'object':
await object(bot)
elif message_type == 'pre_checkout_query':
# Номер карти - 4242 4242 4242 4242
chat_id = request.json["pre_checkout_query"]["from"]["id"]
await add_purchase(bot, chat_id)
pre_checkout_query_id = request.json["pre_checkout_query"]["id"]
await bot.answer_pre_checkout_query(pre_checkout_query_id, True)
# else:
# await other_messages(bot)
return {"get_messages is ok": True}
async def sleep_func():
await asyncio.sleep(20)
print("Hello!")
@app.route('/' + bot_token, methods=['POST'])
async def asynchrony():
#start_time = time.time()
#get_messages_task = asyncio.create_task(get_messages())
#sleep_task1 = asyncio.create_task(sleep_func())
#sleep_task2 = asyncio.create_task(sleep_func())
#await asyncio.wait([get_messages_task, sleep_task1])
#print(time.time() - start_time)
get_messages_task = asyncio.create_task(get_messages())
await asyncio.wait([get_messages_task])
#await get_messages()
return {"asynchrony is ok": True}
@app.route('/')
async def webhook():
await bot.delete_webhook()
await bot.set_webhook(url=app_url)
# chat_id = None
await create_stripe_webhook(app_url, payment_token)
# await test_users()
# await test_films()
# await test_purchases()
# await test_discounts()
# while True:
# time_now = datetime.datetime.now()
# if datetime.date.today().isoweekday() == 4:
# await technical_works(bot)
sleep_task = asyncio.create_task(sleep_func())
await asyncio.wait([sleep_task])
return '!', 200
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))
I will be very appreciative for you help!
My answer is not suitable for this code, which is Flask-app. But it is answer for this question. So you must use Aiogram for asynchrony receiving and processing messages. Aiogram has special decorator async_task
for this: https://docs.aiogram.dev/en/latest/_modules/aiogram/dispatcher/dispatcher.html#Dispatcher.async_task.
If your bot at the same time must perform another function, for example, change data in database once a day, you can create button only for administrator that will start infinity cycle which will sleep for number of seconds in one day.