Как остановить бесконечный цикл командой стоп, которую пишет пользователь в чате телеграм бота? Python
Есть многопользовательский телеграм бот, который по команде запускает парсинг объявлений с сайта. Вызывается функция start_parsing, запускается цикл While True. При получении в чате команды стоп, хендлер ловит команду и вызывается функция stop_parsing, которая должна остановить работу бесконечного цикла
@dp.message_handler(Text(equals="start"))
async def start_parsing(message: types.Message):
await bot.send_message(chat_id=message.from_user.id, text="парсинг запущен")
while True:
#тут код с парсингом
@dp.message_handler(Text(equals="stop"))
async def stop_parsing(message: types.Message):
#тут код, который останавливает цикл While True из функции "start_parsing"
await bot.send_message(chat_id=message.from_user.id, text="парсинг остановлен")
Частично проблема решилась созданием глобальной переменной parsing_continue. Цикл While при каждой итерации проверяет, что она равна True. А по команде стоп в функции stop_parsing эта переменная становится False.
Но это работает только для 1 пользователя. Когда их несколько, команда стоп тормозит парсер всех других пользователей, т.к. переменная глобальная
global parsing_continue
@dp.message_handler(Text(equals="start"))
async def start_parsing(message: types.Message):
await bot.send_message(chat_id=message.from_user.id, text="парсинг запущен")
global parsing_continue
parsing_continue = True
while parsing_continue:
#тут код с парсингом
@dp.message_handler(Text(equals="stop"))
async def stop_parsing(message: types.Message):
global parsing_continue
parsing_continue = False
await bot.send_message(chat_id=message.from_user.id, text="парсинг остановлен")
Возможно, в варианте с глобальной переменной поможет словарь, в котором ключом будут динамически создаваемые переменные parsing_continue, привязанные к id пользователя.
Или существует более подходящая конструкция, чем блокирующий цикл While True.
Может можно как-то создать задачу, которая будет активироваться при старте, и сниматься при стопе.
Сам в питоне новичок, с языком знаком по библиотеке aiogram для ботов. Нагуглил варианты с событийными циклами, creating task, event-loop и тд... Пока не разобрался, это то что нужно, или нет. Подозреваю, что это целая тема для изучения. Буду благодарен если подскажите куда вообще копать
Ответы (1 шт):
Записывайте parsing_continue в хранилище стейта.
from aiogram.dispatcher import FSMContext
from aiogram.contrib.fsm_storage.memory import MemoryStorage
dp = Dispatcher(bot, storage=MemoryStorage())
@dp.message_handler(Text(equals="start"))
async def start_parsing(message: types.Message, state: FSMContext):
await bot.send_message(chat_id=message.from_user.id, text="парсинг запущен")
# записываете в хранилище
await state.update_data({"parsing_continue": True})
# обязательно чтобы делалось именно так, не нужно это в переменную записывать
while (await state.get_data()).get("parsing_continue"):
print(1)
await asyncio.sleep(5)
@dp.message_handler(Text(equals="stop"))
async def stop_parsing(message: types.Message, state: FSMContext):
# просто обновляем данные
await state.update_data({"parsing_continue": False})
await bot.send_message(chat_id=message.from_user.id, text="парсинг остановлен")