Как решить проблему превышения ограничения на метод 'Close' в Aiogram 3?

Как правильно остановить скрипт aiogram2 с поллингом и task'ом в aiogram 3, если при попытке остановки по Ctrl/C возникает ошибка?
  • 15 октября 2023 г. 10:08
Ответы на вопрос 1
Чтобы решить проблему превышения ограничения на метод 'Close' в Aiogram 3, можно использовать декоратор `dp.current_state()` с аргументом `run_task=True`. Это позволит останавливать все текущие задачи, прежде чем закрыть бота. Вот пример кода:

```python
from aiogram import Bot, Dispatcher, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage


bot_token = 'YOUR_BOT_TOKEN'

bot = Bot(token=bot_token)
storage = MemoryStorage()
dp = Dispatcher(bot, storage=storage)

# Твой код

@dp.message_handler(commands=['stop'])
@dp.current_state(run_task=True)
async def stop_bot(message: types.Message):
    await message.answer("Бот остановлен")
    await bot.close()

# Запуск бота
if __name__ == '__main__':
    from aiogram import executor

    executor.start_polling(dp, on_shutdown=stop_bot)
```

Чтобы правильно остановить скрипт aiogram2 с поллингом и task'ом в aiogram 3, можно использовать сигналы операционной системы. Вместо того, чтобы использовать Ctrl/C для остановки, можно отправить сигнал SIGINT (Ctrl/C) или SIGTERM для завершения процесса. Вот пример кода, который может остановить бота при получении одного из этих сигналов:

```python
import asyncio
import signal

from aiogram import Bot, Dispatcher, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage


bot_token = 'YOUR_BOT_TOKEN'

bot = Bot(token=bot_token)
storage = MemoryStorage()
dp = Dispatcher(bot, storage=storage)

# Твой код

async def stop_bot():
    await bot.close()
    await bot.storage.close()
    await bot.storage.wait_closed()
    await dp.storage.close()
    await dp.storage.wait_closed()
    await dp.shutdown_polling()
    for task in asyncio.all_tasks():
        task.cancel()

def on_shutdown(loop):
    asyncio.create_task(stop_bot())

# Запуск бота
if __name__ == '__main__':
    from aiogram import executor

    loop = asyncio.get_event_loop()
    loop.add_signal_handler(signal.SIGINT, on_shutdown, loop)
    loop.add_signal_handler(signal.SIGTERM, on_shutdown, loop)

    executor.start_polling(dp)
```

При получении сигнала SIGINT или SIGTERM вызывается функция `on_shutdown()`, которая запускает асинхронную функцию `stop_bot()`. В этой функции закрываются все соединения и задачи бота перед его остановкой.

Обратите внимание, что для правильной остановки бота необходимо вызывать `bot.close()` и ожидать его закрытия, а также закрыть хранилища состояний и остановить цикл поллинга. Затем отменяются все текущие задачи, чтобы избежать ошибок.
Похожие вопросы