Запуск бота
В программировании точкой входа (entry point) называют часть кода, с которой начинается выполнение программы. Это может быть функция, метод, класс или файл.
В Python обычно в качестве точки входа используют файлы с названиями main или run. Они определяют, откуда стартует выполнение программы, и помогают понять логику её работы.
Я создам файл run.py, где пропишу код, который будет являться точкой входа.
import asyncio
from aiogram import Bot, Dispatcher
bot = Bot(token='123token')
dp = Dispatcher()
async def main():
await dp.start_polling(bot)
if __name__ == '__main__':
asyncio.run(main())
Давайте разберём каждый блок по отдельности.
В этом фрагменте кода создаются объекты — экземпляры классов от Bot и Dispatcher.
Класс Bot принимает в себя токен ранее созданного бота и инициализирует подключение к нему. Мы можем создать несколько таких объектов и подключить их всех к диспетчеру. Вместо «123token» нужно подставить токен, который выдал BotFather.
Dispatcher (далее dp) — это основной роутер, работа происходит через него или в него передают остальные роутеры. Его задача — обрабатывать входящие обновления: сообщения, коллбэки и так далее.
Функция main() является основной функцией программы и точкой входа. Она асинхронная, то есть не блокирует выполнение программы во время работы.
Внутри функции main() происходит обращение к диспетчеру, и вызывается его метод start_polling. В этот метод передаётся объект класса Bot.
Метод start_polling отвечает за отправку запросов на серверы Telegram. Если ответ от сервера есть, бот его обрабатывает. Если ответа нет, функция продолжает ожидать его от Telegram.
Конструкция if __name__ == 'main' запускает функцию main().
Функция main() является асинхронной, поэтому она запускается через модуль asyncio и его метод run(). Это необходимо потому, что запустить асинхронную функцию вне асинхронного контекста мы не можем.
Конструкция if позволяет запускать эту функцию только в том случае, если мы запускаем именно этот файл, а не импортируем его.
Пока что бот просто подключается к Telegram и ожидает обновлений, но не обрабатывает их. Давайте добавим первый обработчик (хэндлер). В итоге код будет выглядеть следующим образом:
import asyncio
from aiogram import Bot, Dispatcher
from aiogram.types import Message
from aiogram.filters import CommandStart
bot = Bot(token='123token')
dp = Dispatcher()
@dp.message(CommandStart())
async def cmd_start(message: Message):
await message.answer('Привет!')
async def main():
await dp.start_polling(bot)
if __name__ == '__main__':
asyncio.run(main())
После инициализации переменных bot и dp, но перед функцией main(), была добавлена ещё одна функция с декоратором.
Это асинхронная функция cmd_start, которая принимает в себя параметр message — объект Message. Это сообщение, которое получает бот от пользователя. В нём хранится множество информации и методов. Внутри функции есть метод message.answer, в который передаётся параметр «Привет!». Это значит, что на полученное от пользователя сообщение бот ответит сообщением «Привет!».
Над функцией находится функция-декоратор dp и его метод message, который принимает класс CommandStart(). Здесь message означает, что хэндлер обрабатывает сообщение, а CommandStart() — это фильтр, то есть какое сообщение будет обрабатывать этот хэндлер — команду /start.
Теперь, имея именно такую конструкцию, мы можем запустить программу. Для этого достаточно ввести команду в терминал.
python run.py
Не забудьте убедиться, что у вас запущено виртуальное окружение.
Теперь можно проверять бота и переходить к дальнейшим действиям.
Чтобы остановить бота, нажмите комбинацию клавиш Ctrl + C. В результате вы получите ошибку.
Вся проблема в последнем участке кода. В документации Python написано:
Raised when the user hits the interrupt key (normally Control-C or Delete);Исключение вызывается, когда пользователь нажимает клавишу прерывания (Ctrl-C или Delete);https://docs.python.org/3/library/exceptions.html#KeyboardInterrupt
Поэтому мы должны словить эту ошибку и проигнорировать следующим образом:
if __name__ == '__main__':
try:
asyncio.run(main())
except:
print('Exit')
Теперь программа работает стабильно:
P.S. Даже если эта статья потеряет свою актуальность, она всё равно будет служить мне напоминанием о некоторых командах и избавит меня от необходимости искать их снова в интернете. Возможно, спустя пару лет я вернусь к этой статье и освежу свои знания. А тем, кто дочитал до конца, я желаю, чтобы ваши труды, проекты и творческие работы всегда оставались актуальными и востребованными! =)