Есть ошибка:
WARNING:aiogram:Goodbye!
Traceback (most recent call last):
File "C:/Users/zahar/Downloads/bot/bot.py", line 21, in
executor.start_polling(dp, skip_updates=True)
File "C:UserszaharDownloadsbotvenvlibsite-packagesaiogramutilsexecutor.py", line 41, in start_polling
executor.start_polling(reset_webhook=reset_webhook, timeout=timeout, relax=relax, fast=fast)
File "C:UserszaharDownloadsbotvenvlibsite-packagesaiogramutilsexecutor.py", line 305, in start_polling
loop.run_until_complete(self._startup_polling())
File "C:UserszaharAppDataLocalProgramsPythonPython38-32libasynciobase_events.py", line 616, in run_until_complete
return future.result()
File "C:UserszaharDownloadsbotvenvlibsite-packagesaiogramutilsexecutor.py", line 356, in _startup_polling
await self._welcome()
File "C:UserszaharDownloadsbotvenvlibsite-packagesaiogramutilsexecutor.py", line 346, in _welcome
user = await self.dispatcher.bot.me
File "C:UserszaharDownloadsbotvenvlibsite-packagesaiogrambotbot.py", line 27, in me
setattr(self, '_me', await self.get_me())
File "C:UserszaharDownloadsbotvenvlibsite-packagesaiogrambotbot.py", line 176, in get_me
result = await self.request(api.Methods.GET_ME, payload)
File "C:UserszaharDownloadsbotvenvlibsite-packagesaiogrambotbase.py", line 201, in request
return await api.make_request(self.session, self.__token, method, data, files,
File "C:UserszaharDownloadsbotvenvlibsite-packagesaiogrambotapi.py", line 104, in make_request
return check_result(method, response.content_type, response.status, await response.text())
File "C:UserszaharDownloadsbotvenvlibsite-packagesaiogrambotapi.py", line 84, in check_result
exceptions.Unauthorized.detect(description)
File "C:UserszaharDownloadsbotvenvlibsite-packagesaiogramutilsexceptions.py", line 137, in detect
raise cls(description)
aiogram.utils.exceptions.Unauthorized: Unauthorized
Я хотел бы сделать так, чтобы когда возникала эта ошибка, код автоматически полностью останавливался при помощи os._exit(0)
, но я не знаю как отловить это исключение или ошибку.
Если написать код, который внизу, то ничего не произойдёт и бот будет дальше работать с этой ошибкой:
if __name__ == "__main__":
try:
executor.start_polling(dp)
except Exception:
os._exit(0)
Установка¶
Для начала давайте создадим каталог для бота, организуем там virtual environment (далее venv) и
установим библиотеку aiogram.
Проверим, что установлен Python версии 3.7 (если вы знаете, что установлен 3.8 и выше, можете пропустить этот кусок):
[groosha@main lesson_01]$ python3.7
Python 3.7.6 (default, Apr 27 2020, 00:17:38)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()
[groosha@main lesson_01]$
Теперь создадим файл requirements.txt
, в котором укажем используемую нами версию aiogram.
О версиях aiogram
В этой главе используется aiogram версии 2.9.2, но перед началом работы рекомендую заглянуть в
канал релизов библиотеки и проверить наличие более новой версии. Подойдёт любая
более новая, начинающаяся с цифры 2, поскольку в будущем ожидается релиз aiogram 3.0 с заметными изменениями
и без обратной совместимости.
Чтобы избежать неприятностей, зафиксируемся на 2.9.2 и далее будем обновляться вручную.
[groosha@main lesson_01]$ python3.7 -m venv venv
[groosha@main lesson_01]$ echo "aiogram==2.9.2" > requirements.txt
[groosha@main lesson_01]$ source venv/bin/activate
(venv) [groosha@main lesson_01]$ pip install -r requirements.txt
# ...здесь куча строк про установку...
Successfully installed Babel-2.8.0 aiogram-2.9.2 aiohttp-3.6.2 async-timeout-3.0.1 attrs-19.3.0 certifi-2020.6.20 chardet-3.0.4 idna-2.10 multidict-4.7.6 pytz-2020.1 typing-extensions-3.7.4.2 yarl-1.5.1
WARNING: You are using pip version 19.2.3, however version 20.2.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(venv) [groosha@main lesson_01]$
Обратите внимание на префикс «venv» в терминале. Он указывает, что мы находимся в виртуальном окружении с именем «venv».
Проверим, что внутри venv вызов команды python
указывает на всё тот же Python 3.7:
(venv) [groosha@main lesson_01]$ python
Python 3.7.6 (default, Apr 27 2020, 00:17:38)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()
(venv) [groosha@main lesson_01]$ deactivate
[groosha@main lesson_01]$
Последней командой deactivate
мы вышли из venv, чтобы он нам не мешал.
Первый бот¶
Давайте создадим файл bot.py
с базовым шаблоном бота на aiogram:
#!venv/bin/python
import logging
from aiogram import Bot, Dispatcher, executor, types
# Объект бота
bot = Bot(token="12345678:AaBbCcDdEeFfGgHh")
# Диспетчер для бота
dp = Dispatcher(bot)
# Включаем логирование, чтобы не пропустить важные сообщения
logging.basicConfig(level=logging.INFO)
# Хэндлер на команду /test1
@dp.message_handler(commands="test1")
async def cmd_test1(message: types.Message):
await message.reply("Test 1")
if __name__ == "__main__":
# Запуск бота
executor.start_polling(dp, skip_updates=True)
Первое, на что нужно обратить внимание: aiogram — асинхронная библиотека, поэтому ваши функции тоже должны быть асинхронными,
а перед вызовами методов API нужно ставить ключевое слово await, т.к. эти вызовы возвращают корутины.
Асинхронное программирование в Python
Не стоит пренебрегать официальной документацией!
Прекрасный туториал по asyncio доступен на сайте Python.
Если вы в прошлом работали с какой-то другой библиотекой для Telegram, например, pyTelegramBotAPI, то концепция
хэндлеров (обработчиков событий) вам сразу станет понятна, разница лишь в том, что в aiogram хэндлерами управляет диспетчер.
Диспетчер регистрирует функции-обработчики, дополнительно ограничивая перечень вызывающих их событий через фильтры.
После получения очередного апдейта (события от Telegram), диспетчер выберет нужную функцию обработки, подходящую по всем
фильтрам, например, «обработка сообщений, являющихся изображениями, в чате с ID икс и с длиной подписи игрек». Если две
функции имеют одинаковые по логике фильтры, то будет вызвана та, что зарегистрирована раньше.
Чтобы зарегистрировать функцию как обработчик сообщений, нужно сделать одно из двух действий:
1. Навесить на неё декоратор, как в примере выше.
С различными типами декораторов мы познакомимся позднее.
2. Напрямую вызвать метод регистрации у диспетчера.
Рассмотрим следующий код:
# Хэндлер на команду /test1
@dp.message_handler(commands="test1")
async def cmd_test1(message: types.Message):
await message.reply("Test 1")
# Хэндлер на команду /test2
async def cmd_test2(message: types.Message):
await message.reply("Test 2")
Давайте запустим с ним бота:
Функция cmd_test2
не работает, т.к. диспетчер о ней не знает. Исправим эту ошибку
и отдельно зарегистрируем функцию:
# Хэндлер на команду /test2
async def cmd_test2(message: types.Message):
await message.reply("Test 2")
# Где-то в другом месте...
dp.register_message_handler(cmd_test2, commands="test2")
Снова запустим бота:
Обработка ошибок¶
При работе бота неизбежно возникновение различных ошибок, связанных не с кодом, а с внешними событиями. Простейший пример:
попытка отправить сообщение пользователю, заблокировавшему бота. Чтобы не оборачивать каждый вызов в try..except
,
в aiogram существует специальный хэндлер для исключений, связанных с Bot API.
Рассмотрим следующий пример кода, имитирующий задержку перед ответом пользователю:
@dp.message_handler(commands="block")
async def cmd_block(message: types.Message):
await asyncio.sleep(10.0) # Здоровый сон на 10 секунд
await message.reply("Вы заблокированы")
За эти 10 секунд пользователь может успеть заблокировать бота со своей стороны и попытка вызвать метод reply
приведёт
к появлению исключения BotBlocked
. Напишем специальный хэндлер для этого исключения:
from aiogram.utils.exceptions import BotBlocked
@dp.errors_handler(exception=BotBlocked)
async def error_bot_blocked(update: types.Update, exception: BotBlocked):
# Update: объект события от Telegram. Exception: объект исключения
# Здесь можно как-то обработать блокировку, например, удалить пользователя из БД
print(f"Меня заблокировал пользователь!nСообщение: {update}nОшибка: {exception}")
# Такой хэндлер должен всегда возвращать True,
# если дальнейшая обработка не требуется.
return True
Аналогично пишутся обработчики и на другие исключения. Таким образом, если одна и та же непредвиденная ситуация может
возникнуть в различных хэндлерах, то можно вынести её обработку в отдельный хэндлер ошибок. Кода будет меньше, а оставшийся
станет читабельнее.
Важно
У errors_handler есть одна особенность, из-за которой его использование может быть нежелательно. Дело в том, что
после срабатывания и завершения хэндлера, управление в исходную функцию не возвращается. Проще говоря, если,
например, 57-я итерация цикла из 100 привела к срабатыванию errors_handler, остальные итерации выполнены не будут,
как и весь остальной код исходной функции. В этом случае ничего не остаётся, кроме как использовать try..except
.
Синтаксический сахар¶
Для того, чтобы сделать код чище и читабельнее, aiogram расширяет возможности стандартных объектов Telegram.
Например, вместо bot.send_message(...)
можно написать message.answer(...)
или message.reply(...)
. В последних
двух случаях не нужно подставлять chat_id
, подразумевается, что он такой же, как и в исходном сообщении.
Разница между answer
и reply
простая: первый метод просто отправляет сообщение в тот же чат, второй делает «ответ» на
сообщение из message
:
@dp.message_handler(commands="answer")
async def cmd_answer(message: types.Message):
await message.answer("Это простой ответ")
@dp.message_handler(commands="reply")
async def cmd_reply(message: types.Message):
await message.reply('Это ответ с "ответом"')
Более того, для большинства типов сообщений есть вспомогательные методы вида
«answer_{type}» или «reply_{type}», например:
@dp.message_handler(commands="dice")
async def cmd_dice(message: types.Message):
await message.answer_dice(emoji="🎲")
что значит ‘message: types.Message’ ?
Python является интерпретируемым языком с сильной, но динамической типизацией,
поэтому встроенная проверка типов, как, например, в C++ или Java, отсутствует. Однако начиная с версии 3.5
в языке появилась поддержка подсказок типов, благодаря которой
различные чекеры и IDE вроде PyCharm анализируют типы используемых значений и подсказывают
программисту, если он передаёт что-то не то. В данном случае подсказка types.Message
соообщает
PyCharm-у, что переменная message
имеет тип Message
, описанный в модуле types
библиотеки
aiogram (см. импорты в начале кода). Благодаря этому IDE может на лету подсказывать атрибуты и функции.
При вызове команды /dice
бот отправит в тот же чат игральный кубик. Разумеется, если его надо отправить в какой-то
другой чат, то придётся по-старинке вызывать await bot.send_dice(...)
. Но объект bot
(экземпляр класса Bot) может быть
недоступен в области видимости конкретной функции. К счастью, объект бота доступен во всех типах апдейтов: Message,
CallbackQuery, InlineQuery и т.д. Предположим, вы хотите по команде /dice
отправлять кубик не в тот же чат, а в канал
с ID -100123456789. Перепишем предыдущую функцию:
@dp.message_handler(commands="dice")
async def cmd_dice(message: types.Message):
await message.bot.send_dice(-100123456789, emoji="🎲")
Всё хорошо, но если вдруг вы захотите поделиться с кем-то кодом, то придётся каждый раз помнить об удалении
из исходников токена бота, иначе придётся его перевыпускать у @BotFather. Чтобы обезопасить себя,
давайте перестанем указывать токен прямо в коде, а вынесем его как переменную окружения.
Замените следующие строчки из начала файла:
import logging
from aiogram import Bot, Dispatcher, executor, types
bot = Bot(token="12345678:AaBbCcDdEeFfGgHh")
на эти:
import logging
from aiogram import Bot, Dispatcher, executor, types
from os import getenv
from sys import exit
bot_token = getenv("BOT_TOKEN")
if not bot_token:
exit("Error: no token provided")
bot = Bot(token=bot_token)
Но теперь ваш бот не запустится, т.к. будет сразу завершаться с ошибкой Error: no token provided
.
Чтобы передать переменную окружения в PyCharm, откройте сверху раздел Run -> Edit Configurations
и добавьте в окне Environment Variables переменную с именем BOT_TOKEN и значением токена.
Запустите снова бота и убедитесь, что он работает. Получившийся код можно смело сохранять в
PyCharm в File Templates.
На этом мы закончим знакомство с библиотекой, а в следующих главах рассмотрим другие «фишки» aiogram и Telegram Bot API.
Ошибки в ботах и как их читать
LatandХочешь научиться писать ботов? Проходи и смотри бесплатные уроки на площадке Botfather.Dev
В первую очередь, давайте разделим 3 типа ошибок:
- Ошибки в Python — например, когда вы делите на ноль
- Ошибки при работе с Telegram Bot API — например, когда вы пытаетесь отправить сообщение ботом несуществующему пользователю
- Прочие ошибки, при работе с другими библиотеками.
Когда возникает ошибка в коде, вы ее узнаете (обычно) по красному цвету текста и кучи строк, которые вы не планировали выводить. Мы рассмотрим наиболее часто повторяющиеся ошибки. Но, возможно вашей ошибки тут не будет.
Сначала мы научимся читать ошибки, чтобы понимать, что вообще с ними можно делать, а потом разберем типичные ошибки с Python и в Telegram bot API и как их решать.
Содержание статьи
├── Как читать код ошибки? ├── Что писать в чат, если возникла ошибка? ├── Типичные ошибки в Python ├── Типичные ошибки при работе с Telegram Bot API ├── Прочие ошибки
Как читать код ошибки?
Лучше всего это показать на примере. Эту ошибку прислал один из студентов, мы её и разберем. Как обычно, много красного текста, но! Это не должно вас пугать.
Самое важное — надо определить, что это таки именно ошибка, а не что-то другое, а это можно сделать по слову Traceback где-то вначале красного текста. Если там такое есть — это ошибка.
Тут и начинается код ошибки. Traceback — («trace», «back») с английского «отследить» и «назад«. Т.е. прослеживаем откуда эту ошибка пришла.
Смотрим сверху вниз, сначала в файле (слово File) по пути D:Pythonaiogram-bot-template
…. и потом смотрим в конец строки
Видим в конце
dispatcher.py, line 388, in _process_polling_updates
Это то, откуда эта ошибка появилась позже всего и на чём всё сломалось. Но это не то место, где вы допустили ошибку! Это файл dispatcher.py
, который лежит по определенному пути, и в нем на 388 строке, в функции _process_polling_updates
(обработка обновлений поллинга) возникла ошибка ошибка в каком-то таком месте:
Все еще сложно понять, что это такое. Вы это не писали? Точно?
Странно… Я тоже этого не писал.
А! Там же ниже еще есть код, оказывается тут выполнялся код функции
await self.process_updates(updates, fast)
А внизу есть код ошибки и этой функции!
Смотрим туда. Там пишет, что ошибка в том же dispatcher.py, в котором выполнялся код функции:
await asyncio.gather(*tasks)
Ну это то точно вы писали! Нет? Уверены???
Значит смотрим ниже.
Дальше идет выполнение какой-то функции:
handler_obj.handler(*args, **partial_data)
В строке 117, в функции notify.
Ну, короче вы поняли, смотрим дальше, пока не появится что-то знакомое.
А! нашел!
Папка, где ученик хранит свой проект называется «Проект», в нем есть папка aiogram-bot-template. Похоже на то.
И тут смотрим как обычно на то, где ошибка возникла, где-то в обоих файлах:
menu_handlers db_commands
Внимательно!
Сначала выполнилась функция navigate на строке 118, потом list_tiker на строке 74, а потом update_userstiker, в которой выполнилась функция:
await user_tiker.create()
Вот оно! Вот это место, где ученик допустил ошибку. Но не похоже на то, что тут что-то сделано не так. Да и внизу есть какой-то код. Но в любом случае, это 100% то место, где ученик допустил ошибку.
Внизу можно прочитать следующее:
Ошибка RuntimeError: cannot reuse already awaited coroutine
. Если английский вам не сильно знаком, а с питоном вы еще пытаетесь подружиться, но до асинхронности еще не дошли, то для вас это будет полной белибердой.
Пытаемся решить ошибку…
Для начала, пробуем прочитать ошибку и перевести ее. Очень часто в самой ошибке содержится уже её решение.
Если это не помогло — пробуем копировать ошибку и просто-напросто ГУГЛИТЬ! ДА!
https://stackoverflow.com/questions/51116849/asyncio-await-coroutine-more-than-once-periodic-tasks
Вот например, один из примеров ответа на эту ошибку. Чаще всего ответы вы найдете на stackoverflow практически на все ошибки!
Если там на английском — не страшно, переводите страницу, благо Google Chrome позволяет это делать максимально просто. А еще лучше, сначала попробуйте саму ошибку перевести!
На том посте видим ответ с галочкой:
Тут говорится, что возможно человек путает асинхронные функции с корутинами (сопрограммами). В данном примере sample
— функция (или ссылка) на асинхронную функцию, а sample()
— уже корутина. И, чтобы забрать данные из корутины, и ее выполнить, необходимо сделать сначала await перед ней.
Почитав немного других постов я понял, что загвоздка в том, что корутину можно await-ить только один раз! Сделать await sample
можно всего один раз.
Значит можно сделать предположение, что user_tiker, перед которым стоит await уже был ранее await-нут. Но, на этом мои догадки заканчиваются…
Ах да, тут ученику, по этой ошибке подсказали:
А вот тут похоже, что сначала происходит await id_tiker и потом он передается в User_Tiker. Не уверен в чем тут дело, но возможно gino пытается внутри что-то await-ить, а может быть ученик сделал что-то, но не показал, и поэтому мы можем только гадать в чем была проблема, потому что позже он написал:
Ну, главное, что решил!
Ах да, мы ж тут не конкретную ошибку разбирали, а возможный путь её решения.
Подытожим:
- Ищем Traceback
- Читаем его и пытаемся найти то последнее место в коде, где ВЫ могли допустить ошибку. То есть в том, что писали именно вы.
- В крайнем случае — обращаемся к концу кода и читаем именно Exception или Error.
- Гуглим этот Exception/Error и ищем пути решения.
- Отслеживаем в других функциях выше, где вы могли допустить ошибку.
- Если ничего не находите дельного — пишите в чаты.
Я не нашел решения! Что писать в чат, когда возникла ошибка?
Очень просто. Есть несколько важных моментов:
- Пишите вежливо, никто не обязан за вас решать ваши ошибки, но кто-то найдется, чтобы помочь.
- Опишите проблему, если можно, в одном сообщении.
- Опишите то, что вы пытались сделать, и какие у вас предположения! Никто не любит помогать тем, кто сразу пишет в чат и не гуглит.
- Залейте ВЕСЬ Traceback на pastebin.com или dpaste.org
- Можете добавить часть вашего кода, где у вас возникает ошибка, берите функции и строки из трейсбека + 10-20 строк по вниз и вверх, чтобы был понятен контекст проблемы.
Ошибки в Python
Ошибок в Python может быть очень много и зависит от контекста. Для того, чтобы они не возникали — надо учить питон. Ага, все таки придется…
Почитать о них всех можно тут: https://docs.python.org/3/library/exceptions.html#concrete-exceptions
Те, с которыми часто сталкиваются:
SyntaxError — ошибка при работе с синтаксисом Python
Пожалуй, самая распространенная ошибка… Если бы все начинали не с ботов, а с изучения языка программирования Python, то было бы лучше!
Она возникает, когда вы просто неправильно ввели код. Когда возникает?
- Опечатались при создании функции/класса. Ввели не
def dunc():
, а
defc func():
Или
clas MyClass():
, вместо
class MyClass():
- Не поставили скобочки/двоеточие/знак равно, где нужно. Например, при создании функции:
def a: return 1
- Не закрыли скобки
- Не поставили кавычки, когда записываете текст в переменную:
BOT_TOKEN = 1223423543:IOFNGVOIWENOGIBWENIOGEWRNGVEW
- Используете зарезервированные имена функций в питоне
ImportError — ошибка при работе с импортами.
- Ошибка импорта библиотеки, очень часто при цикличном импорте. То есть, вы в файле
a
, импортируете функцию из модуляb
. При этом, в модулеb
у вас что-то импортируется из модуляa
. И питон начинать ходить по кругу и импортировать одно из другого (нет).
Сделайте так, чтобы не пришлось из модуля a
импортировать что-то в b
. Переместите эту функцию в модуль c
.
- А еще бывает такое:
Если вы запускаете код бота, но не из того модуля, где идет запуск поллинга, а где просто обозначены хендлеры. Этот файл не надо запускать.
ModuleNotFoundError — не установлена библиотека.
Да. Не установлена. Установите ее с помощью pip install <имя библиотеки>
, но перед этим убедитесь, что вы ввели правильное название ее из pypi
. Названия можно глянуть тут: https://pypi.org/project/pip/
- А еще, может быть просто вы пытаетесь импортировать файл из своего проекта, но он лежит в другой папке
TypeError — ошибка при работе с типами данных.
Это может произойти, когда вы используете неправильные методы для работы с объектами. Например, вы попытались сложить текст с числом.
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Но еще может возникнуть, когда вы работаете с вызовом функций:
TypeError: func() takes 1 positional argument but 2 were given
В функцию передаете больше аргументов, чем она ждет.
TypeError: func() got multiple values for argument 'a'
Когда вы передаете в функцию несколько значений для одной переменной.
TypeError: func() missing 1 required positional argument: 'a'
Когда вы в функцию не передали нужные аргументы, например positional — те, что идут по порядку
TypeError: my_func() missing 1 required positional argument "self"
Это довольно частая ошибка, когда вы работаете с классом, который не инициализирован.
Например, есть класс Bot
, у него есть метод get_me
, вы пытаетесь запустить функцию Bot.get_me()
. И, несмотря на то, что класс имеет этот метод, пока вы не выполните функцию __init__
, в которой создастся self
, у вас будет эта ошибка.
Функция инит выполняется когда вы создаете экземпляр класса. Как-то так: bot = Bot()
. Только после этого можно сделать bot.get_me()
TypeError: object function can't be used in `await` expression
Похоже, что кто-то забыл, что await-ить можно только асинхронные функции, а не обычные. Либо уберите await
, либо сделайте функцию асинхронной, с помощью приставки async: async def my_func(): ...
- TypeError: «coroutine» object is not subscriptable
Тут ошибка говорит, что мы не можем достать элемент из корутины. Типа если сделать await bot.get_me()["username"]
. Вообще, есть порядок выполнения кода, и тут сначала питон пытается достать элемент по ключу username из корутины bot.get_me()
, а потом только он сделает await.
В данном случае, нам надо сначала сделать await, потому мы заключим этот фрагмент в скобки:
(await bot.get_me())["username"]
И тогда все выполнится.
Но ошибка заключается в том, что данный тип объекта не позволяет брать элементы таким способом ["element"]
, или по индексу [2]
.
RuntimeWarning: coroutine ‘my_func’ was never awaited
… RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Не совсем ошибка, но все же частая проблема. У вас была корутина my_func
(или другое название), к которой вы не прописали await
. Скорее всего вы это должны сделать, поэтому вернитесь и await-ните вашу корутину! Сделайте await my_func()
ValueError — ошибка при работе со переданными значениями.
Возникает, когда вы передаете в функцию значение правильного типа, но неправильного значения. Примеры:
- Переданный символ
":"
(двоеточие) используется функцией для разделения значений в CallbackData, поэтому его нельзя использовать в самих значениях. Это может произойти, когда вы работаете с CallbackData Factory
- Длина callback_data в инлайн кнопках ограничена 64-ю байтами. Бывают такие ошибки:
- Пытаетесь из текста сделать int
AttributeError — ошибка при работе с атрибутами классов.
Такая ошибка возникает, когда вы пытаетесь вызвать атрибут (переменную класса), которую этот класс не имеет.
Примеры:
AttributeError "NoneType" object has no attribute "run_until_complete"
Довольно частая ошибка, когда пытаются сделать dp.loop.run_until_complete
, а dp.loop
оказывается равен None
. Ну и когда этот объект «ничто», у него и не может быть никаких атрибутов. P.S. Никогда не берите loop из объекта dp.
Ошибки при работе с Telegram Bot API
Вообще, частенько, при работе с Бот АПИ, в ошибке указано решение… Но его почему-то не читают.
aiogram.utils.exceptions.TerminatedByOtherGetUpdates
У вас запущено более одного процесса, которые делают запрос getUpdates
к телеграму с одного и того же токена бота Т.е. когда в боте запускается функция start_polling несколько раз в разных процессах.
Вы либо не остановили один процесс и запустили код заново, либо закрыли неправильно Pycharm, не останавливая процесс, и потом запустили бота заново. Либо у вас работает бот на сервере, а вы еще и запускаете на локальном компьютере.
Пожалуйста, найдите этот второй процесс и убейте его. Можно просто перезагрузить компьютер. А если не можете найти — смените токен бота и все решится.
aiogram.utils.exceptions.ChatNotFound
Ошибка возникает, если:
- Вы ввели неверный идентификатор чата (просто неправильное значение передано в аргумент
chat_id
) - Бот не контактировал с пользователем ранее, поэтому он не может ему написать.
aiogram.utils.exceptions.CantParseEntities
В тексте у вас закрался запрещенный символ.
Обычно, если вы используете parse_mode для форматирования текста (HTML или MARKDOWN), то для того, чтобы понять где у вас в тексте жирный шрифт или курсив — используются специальные символы/теги. Примеры:
- Для HTML жирный шрифт будет
<b>жирный</b>
. Поэтому, если в тексте будет что-то типа<coroutine>,
то телеграм его не распознает и выдаст эту ошибку - Для HTML используемые теги надо закрывать, т.е. если вы начали с тегом
<b>
, то где-то его надо закрыть:</b>
- Для MARKDOWN жирный шрифт будет
*жирный*
. Поэтому, если где-то в тексте будет нечётное количество звездочек, т.е. в тексте где-то появилась звездочка, которой вы не хотели текст сделать жирным — будет ошибка.
Ошибку можно решить с помощью функций quote_html или escape_md:
from aiogram.utils.markdown import quote_html text = quote_html("<booo>")
aiogram.utils.exceptions.BadRequest
Название ошибки ни о чем не говорит. Просто то, что запрос не состоялся. А вот решение написано в описании ошибки. Например:
Not enough rights to export chat invite link
— У бота недостаточно прав для того, чтобы создать ссылку-приглашение в чат. Скорее всего он не админ, или просто не имеет на это право.
aiogram.utils.exceptions.ValidationError: Token is invalid!
Все просто, как описано в ошибке. Вы ввели неверный токен. Можете проверить это с помощью функции print. Попробуйте print(BOT_TOKEN)
если у вас эта переменная так называется, и убедитесь сами.
Как Частенько такое вижу, когда мои студенты не переименовывают файл .env.dist в .env.
АЛЛО! Расширение dist используется для примеров файлов, а не для того, чтобы туда писались переменные! Переименуйте и тогда подтянется уже ваш токен из файла .env.
aiogram.utils.exceptions.RetryAfter
В телеграме есть лимиты. Например, сообщения советуют слать не чаще 1 секунды в один и тот же чат. Делайте иногда задержки в своем коде между отправкой нескольких сообщений:
await asyncio.sleep(1)
Прочие ошибки
Тут довольно специфичные ошибки, на случай, если вы не нашли выше описание нужной.
ERROR: Command errored out with exit status 1:…
Если у вас именно такая ошибка, или похожая как на скрине — у вас не установилась библиотека на Python3.9. Эта версия на Windows еще не отлажена окончательно, поэтому решение тут — удалить Python3.9 и поставить Python3.8
asyncpg.exceptions.InvalidCatalogNameError: database «…» does not exist
Тут библиотека asyncpg сообщает вам, что в вашей базе данных отсутствует база с именем, указанным в кавычках.
sqlite3.OperationalError: near «)»: syntax error
Синтаксическая ошибка в вашем SQL-запросе. Проследите строчку, где этот запрос делается и проверьте где вы написали что-то несусветное рядом со скобкой. Либо не рядом со скобкой (в ошибке будет написано в кавычках).
Home>2021-08-30 15:12
python : How to stop Telegram Bota (Aiogram) with any error?
Telegram Bot written in python using the aiogram library . There is a need to stop the bot and close program when there are errors that relate directly Aiogram library.
as an example of an error you can consider (
Or any other which occurs within the Aiogram library) :
Aiogram.utils.Exceptions.TerminatedByothergetUpdates: Terminated by Other Getupdates Request; Make Sure That Only One Bot Instance IS Running
If you briefly here:
From Aiogram Import Bot, Types
From aiogram.dispatcher Import Dispatcher
from aiogram.utils import executor
From Config Import Token
if __name__== '__main__':
Bot= Bot (Token= Token)
DP= DISPATCHER (BOT)
Executor.Start_Polling (DP)
tried to wrap
Executor.Start_Polling (DP)
In the design
Try, Except
. However it did not help because the error occurred inside
Executor.Start_Polling (DP)
And thereby did not have any influence on
Try, Except
main function.
What needs to be done to stop the bot in case of errors and the closure of the program itself?