Как исправить ошибку fetchall в Telegram боте на Python
При разработке ботов на Python с библиотекой aiogram и aiosqlite новички часто сталкиваются с ошибкой AttributeError: 'Connection' object has no attribute 'fetchall'. Эта проблема возникает из-за неправильного порядка выполнения запроса к базе данных. В этой статье мы подробно разберём, как правильно выполнять SELECT-запросы и выводить найденные строки.
Почему возникает ошибка fetchall?
Ошибка AttributeError говорит о том, что у объекта Connection нет метода fetchall(). В библиотеке aiosqlite (и стандартном sqlite3) метод fetchall() принадлежит объекту Cursor, а не самому соединению. После вызова await db.execute() возвращается курсор, который и нужно использовать для получения данных.
Правильный способ запроса к SQLite
Чтобы избежать ошибки, нужно сохранить результат db.execute() в переменную-курсор, а затем вызвать у него fetchall(). Кроме того, важно правильно подставлять значение переменной message_name - использовать параметризованный запрос, а не просто строку в кавычках.
Исправленный код:
@start_router.message(Form.search_for_name)
async def search_name(message: types.Message):
message_name = message.text.strip()
async with aiosqlite.connect('base.db') as db:
cursor = await db.execute(
'SELECT username, user_tg, name, soname FROM user WHERE [name] = ?',
(message_name,)
)
users = await cursor.fetchall()
if users:
users_str = '\n'.join([str(user) for user in users])
await message.answer(users_str)
else:
await message.answer('Совпадений не найдено.')
await db.commit()Ключевые изменения:
- cursor = await db.execute(...) - получаем курсор.
- await cursor.fetchall() - вызываем метод у курсора.
- WHERE [name] = ? - используем плейсхолдер
?и передаём значение кортежем(message_name,). - Добавлена проверка
if users:, чтобы не отправлять пустой список.
Дополнительные советы для работы с SQLite в aiogram
При разработке ботов с базой данных важно учитывать несколько моментов:
- Параметризация запросов - всегда используйте
?вместо конкатенации строк, чтобы избежать SQL-инъекций. - Асинхронность - все операции с aiosqlite должны быть с
await. - Закрытие соединения - контекстный менеджер
async withавтоматически закроет соединение после выхода. - Обработка пустого результата - проверяйте, что
fetchall()вернул хотя бы одну запись.
Пример с форматированием вывода
Чтобы данные выглядели читаемо, можно отформатировать каждую строку вручную:
if users:
lines = []
for u in users:
lines.append(f'Имя: {u[2]}, Фамилия: {u[3]}, Юзернейм: {u[0]}, ID: {u[1]}')
await message.answer('\n'.join(lines))Этот подход делает ответ бота более информативным и удобным для пользователя.
Заключение
Ошибка fetchall у соединения - типичная ловушка для начинающих. Запомните: после await db.execute() обязательно используйте курсор для вызова fetchall(). Следуя нашим рекомендациям, вы сможете легко выводить нужные строки из базы данных в Telegram боте.