Почему PostdgreSQL постоянно выдает ошибку AttributeError: 'NoneType' object has no attribute 'fetchall'?
Здравствуйте!
С недавнего времени пришлось перейти с SQLite на PostdgreSQL
что ж при адаптировании кода к библиотеке psycorg2 выдает ошибку ко всем атрибутам fetchall() во всех функциях :
return result.fetchall()
AttributeError: 'NoneType' object has no attribute 'fetchall'
Да, дата база пустая, но у меня стоит условие, если она нет id - пропускай дальше, то есть в sqlite все это работало, сейчас же я просто мб ошибаюсь в синтаксисе. Прошу помочь советом)
Дальше мой код обращения к дб:
def __init__(self, database_file): """Подключаемся к Базе Данных и сохраняем курсор соединения""" self.connection = psycopg2.connect(user="user", password="pass", host="localhost", port="5432", database=database_file) #self.connection = sqlite3.connect(database_file) self.connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) self.cursor = self.connection.cursor() def client_exists(self, user_id): """Проверяем есть ли клиент уже в базе данных""" result = self.cursor.execute("""SELECT * FROM clients WHERE user_id = %s""", (user_id,)) return bool(len(result.fetchall())) def get_new_logo(self): """Получаем картинку""" result = self.cursor.execute("""SELECT logo FROM logotype WHERE id = 1""") return result.fetchall() |
def __init__(self, database_file): """Подключаемся к Базе Данных и сохраняем курсор соединения""" self.connection = psycopg2.connect(user="user", password="pass", host="localhost", port="5432", database=database_file) #self.connection = sqlite3.connect(database_file) self.connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) self.cursor = self.connection.cursor() def client_exists(self, user_id): """Проверяем есть ли клиент уже в базе данных""" result = self.cursor.execute("""SELECT * FROM clients WHERE user_id = %s""", (user_id,)) return bool(len(result.fetchall())) def get_new_logo(self): """Получаем картинку""" result = self.cursor.execute("""SELECT logo FROM logotype WHERE id = 1""") return result.fetchall()
Код бота:
@dp.message_handler(commands=("start", "Начать")) @dp.message_handler(Text(equals=('начать', 'start'), ignore_case=True)) async def start(message: types.Message): logo = db.get_new_logo() for r in logo: if r[0] == 1: await message.answer_photo(r[2]) if (not db.client_exists(message.from_user.id)): await message.answer( text=f'Добро пожаловать, Что ж, начнем сотрудничество?',reply_markup=nav.start_menu) else: await message.answer( text=f'C возвращением , {message.from_user.first_name} !nnВыберите пункт меню.', reply_markup=nav.main_choise) |
@dp.message_handler(commands=("start", "Начать")) @dp.message_handler(Text(equals=('начать', 'start'), ignore_case=True)) async def start(message: types.Message): logo = db.get_new_logo() for r in logo: if r[0] == 1: await message.answer_photo(r[2]) if (not db.client_exists(message.from_user.id)): await message.answer( text=f'Добро пожаловать, Что ж, начнем сотрудничество?',reply_markup=nav.start_menu) else: await message.answer( text=f'C возвращением , {message.from_user.first_name} !nnВыберите пункт меню.', reply_markup=nav.main_choise)
Дополнительно:
Это ошибка не СУБД. Чтобы убедиться в этом - посмотрите постгресовский лог.
Смотрите на какую строку ругается при ошибке, почему атрибут NoneType, возможно будет иметь атрибут fath
File "D:Phyton35thParallelBothandlersusersgreates.py", line 29, in start
logo = db.get_new_logo()
File "D:Phyton35thParallelBotdb_connect.py", line 162, in get_new_logo
return result.fetchall()
AttributeError: 'NoneType' object has no attribute 'fetchall'
Данные не возвращаются в вашу переменную. Они лежат в курсоре.
def client_exists(self, user_id): """Проверяем есть ли клиент уже в базе данных""" self.cursor.execute("""SELECT * FROM clients WHERE user_id = %s""", (user_id,)) return bool(len(self.cursor.fetchall())) |
def client_exists(self, user_id): """Проверяем есть ли клиент уже в базе данных""" self.cursor.execute("""SELECT * FROM clients WHERE user_id = %s""", (user_id,)) return bool(len(self.cursor.fetchall()))
И можно сделать немного вот так (если не путаю):
def client_exists(self, user_id): """Проверяем есть ли клиент уже в базе данных""" self.cursor.execute("""SELECT * FROM clients WHERE user_id = %s""", (user_id,)) return self.cursor.fetchone() is not None |
def client_exists(self, user_id): """Проверяем есть ли клиент уже в базе данных""" self.cursor.execute("""SELECT * FROM clients WHERE user_id = %s""", (user_id,)) return self.cursor.fetchone() is not None
- Ага, я привык к sqlite3 что там все через connection, тоже уже тоже методом тыка понял self.cursor. fetchone() работает, спасибо:)
Ответы:
Я полагаю, есть два способа сигнализации о пустом ответе, и разные движки используют разные подходы.
Либо БД может вернуть объект-курсор, который не содержит ни одной строки.
Либо БД может вернуть None.
Для понятности такая аналогия: пусть нам возвращают список. Если нам всегда возвращают список, то можем писать код так:
for line in db.query("..."): do_something(line) |
for line in db.query("..."): do_something(line)
Сработает даже еслди в ответе нет ни одной строки, т.е. на пустом списке.
А вот если нам при пустом ответе возвращают None, то код выше вылетит с ошибкой NoneType is not iterable, и надо будет переписать так:
result = db.query("...") if result is not None: for line in result: do_something(line) |
result = db.query("...") if result is not None: for line in result: do_something(line)
- Хорошее решение, тоже пробовал что-то подобное, но к сожалению ни Ваше, ни мое не помогло, ошибку все равно он выдает связанную с result.fetchall() :(
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Ошибка AttributeError: 'NoneType' object has no attribute 'fetchall' обычно возникает, когда метод fetchall вызывается на объекте, который равен None. Это означает, что запрос к базе данных не вернул никаких результатов, и вместо списка результатов вернулся объект None.
Чтобы избежать этой ошибки, необходимо проверить результат выполнения запроса к базе данных перед вызовом метода fetchall. В примере ниже показано, как это можно сделать в Python с использованием библиотеки psycopg2 для работы с PostgreSQL:
```python
import psycopg2
# устанавливаем соединение с базой данных
conn = psycopg2.connect("dbname=test user=postgres password=secret")
# создаем курсор для выполнения запросов
cur = conn.cursor()
# выполняем SQL запрос
cur.execute("SELECT * FROM table_name")
# получаем результат выполнения запроса
result = cur.fetchone()
# проверяем, что результат не равен None
if result is not None:
# если результат не равен None, то можно вызывать метод fetchall
rows = cur.fetchall()
for row in rows:
print(row)
else:
print("Результат пустой")
# закрываем курсор и соединение
cur.close()
conn.close()
```
В этом примере мы сначала вызываем метод fetchone, чтобы получить одну строку результата. Затем мы проверяем, что результат не равен None, и только после этого вызываем метод fetchall для получения всех оставшихся строк результата.
Таким образом, следует всегда проверять результат выполнения запроса к базе данных на равенство None перед вызовом метода fetchall, чтобы избежать ошибки AttributeError.