Как можно исправить ситуацию, когда обработчик @dp.message_handler() не срабатывает из-за цикла while?

Здравствуйте!
У меня возникла проблема при написании бота. Я использую цикл while, который должен работать до тех пор, пока я (пользователь) не отправлю боту другое сообщение с другим текстом. Кажется, что хэндлер не срабатывает из-за того, что цикл не прекращается. Я уже попробовал использовать break и изменять условие вручную, но это не помогло. Вот пример кода:

@dp.message_handler(state='*', text=['Фрукты'])
async def fruits(message: types.Message, state:FSMContext):
    if message.text == "Фрукты":
          #код

@dp.message_handler(state='*', text=['Ягоды'])

Буду благодарен за любую помощь!
  • 15 сентября 2023 г. 23:27
Ответы на вопрос 2
Проблема возникает из-за того, что цикл while блокирует выполнение асинхронных функций, включая обработчики сообщений в вашем телеграм-боте. 

Одним из способов исправить эту ситуацию является использование асинхронного цикла, такого как `asyncio`, вместо обычного цикла while. В этом случае, вместо цикла while, вы можете использовать `asyncio.Event`, чтобы ожидать отправки нового сообщения пользователем.

Ниже приведен пример кода, который может помочь вам решить проблему:

```python
import asyncio

stop_event = asyncio.Event()

@dp.message_handler(state='*', text=['Фрукты'])
async def fruits(message: types.Message, state:FSMContext):
    if message.text == "Фрукты":
        # код
        stop_event.set()

@dp.message_handler(state='*', text=['Ягоды'])
async def berries(message: types.Message, state:FSMContext):
    if message.text == "Ягоды":
        # код
        stop_event.set()

async def wait_for_commands():
    while not stop_event.is_set():
        await asyncio.sleep(0.1)  # Ждем 0.1 секунду перед проверкой stop_event

async def main():
    await asyncio.gather(dp.start_polling(), wait_for_commands())

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
```

В этом примере мы используем `asyncio.Event` `stop_event`, чтобы определить, когда остановить цикл `wait_for_commands()`. Когда пользователь отправляет боту сообщение с текстом "Фрукты" или "Ягоды", соответствующие обработчики сообщений вызывают `stop_event.set()`, что приводит к остановке цикла.

Определите свою бизнес-логику внутри соответствующих обработчиков сообщений, и используйте `await` перед асинхронными операциями, чтобы дать возможность другим обработчикам вызываться.

Надеюсь, это поможет вам исправить проблему и добиться работы вашего обработчика сообщений.
Цикл (условие) должен быть здесь: message.text == "Фрукты". 

Совет: Создайте глобальную переменную, в которой будет храниться последнее сообщение, и при получении нового сообщения выполните проверку с помощью этой переменной. 
Пример:

LAST_MESSAGE = None

@dp.message_handler(state='*', text=['Фрукты'])
async def fruits(message: types.Message, state:FSMContext):
    if message.text == LAST_MESSAGE:
        return
    # Ваша логика
    LAST_MESSAGE = message.text
Похожие вопросы