DictCursor не работает под psycopg2
Я раньше не работал с psycopg2, но я пытаюсь изменить курсор factory на DictCursor, чтобы fetchall или fetchone вернули словарь вместо списка.
Я создал тест script, чтобы сделать вещи простыми и только проверить эту функциональность. Здесь мой маленький код, который, как мне кажется, должен работать
import psycopg2
import psycopg2.extras
conn = psycopg2.connect("dbname=%s user=%s password=%s" % (DATABASE, USERNAME, PASSWORD))
cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor)
cur.execute("SELECT * from review")
res = cur.fetchall()
print type(res)
print res
Переменная res всегда представляет собой список, а не словарь, как я ожидал.
В текущем обходном пути, который я реализовал, используется эта функция, которая строит словарь и запускает каждую строку, возвращенную fetchall через нее.
def build_dict(cursor, row):
x = {}
for key,col in enumerate(cursor.description):
x[col[0]] = row[key]
return d
Python - версия 2.6.7, а psycopg2 - версия 2.4.2.
Ответы
Ответ 1
res = cur.fetchall()
делает res
список psycopg2.extras.DictRow
s.
В качестве альтернативы вместо вызова cur.fetchall
вы можете воспользоваться тем, что cur
является итерабельным:
cur.execute("SELECT * from review")
for row in cur:
print(row['column_name'])
и, таким образом, вы сможете получить доступ к данным с синтаксисом dict
.
Ответ 2
Использовать RealDictCursor:
cur = conn.cursor(cursor_factory = psycopg2.extras.RealDictCursor)
cur.execute("SELECT * from review")
res = cur.fetchall()
Это дает вам список со строками как настоящие словари python, а не "расширенный список psycopg2".
Ответ 3
Другим решением было бы использовать Named Tuple Cursor, поскольку курсор Real Dict будет разбивать любой запрос, который использует целые знаки, как описано в его документации.
С помощью Named Tuple Cursors вы можете получить доступ к ним с помощью синтаксиса точек так:
import psycopg2
import psycopg2.extras
cur = conn.cursor(cursor_factory = psycopg2.extras.NamedTupleCursor)
cur.execute("SELECT * from review")
res = cur.fetchone()
res.key1
res.key2
Это держит вещи в порядке и ничего не сломает, насколько я знаю.
Ответ 4
В то время как это старый вопрос, он все еще появляется в google, поэтому я думал, что добавлю свой код к этому для любого другого, выходящего из большого G.
Для меня у меня есть несколько строк, которые я хотел бы вернуть обратно в словарь, и в идеале не хочу использовать цикл или аналогично, чтобы установить ключ из поля в базе данных.
Таким образом, используя dict comprehension syntax
, я могу сделать следующее.
Табличные строки в словаре
pgCursor = Conn.cursor(cursor_factory = psycopg2.extras.RealDictCursor)
pgCursor.execute("SELECT * FROM tablename;",([]))
dictRows = {n['id']: n for n in pgCursor}
Функция и вызов
#NOTE this is using a class object hence the self param
def DBTableToDictByID(self, squery):
self.Pointer.execute(squery,([]))
return {n['id']: n for n in self.Pointer}
dictRows = self.DBTableToDictByID("SELECT * FROM tablename;")
В то время как это использует for for x in y, его питонов, насколько я могу сказать.... Надеюсь, это поможет кому-то.
Ответ 5
В дополнение к использованию функции RealDictCursor вам также может потребоваться задать все столбцы
(используя символ * после выбора), как это сделано в ответе.
Меня не интересовали некоторые столбцы результата, так как они знали значения
уже используется в условиях WHERE. Но SELECT (..., ..., ..., ...) FROM ... WHERE ...
вариант не дал мне словарей.
С уважением!
Harley
Ответ 6
Итак, чтобы эта работа была похожа на версию курсора Dictionary mysql, вам придется обернуть ее другой функцией или кодом. Я поеду на форумы и предлагаю это им для будущих развертываний своего кода, чтобы вернуть словарь, когда вызов fetchall() используется с Курсором словаря. Вот пример кода, который вы можете исправить для него:
cursor.execute(query)
# Python 2.7 and beyond with dictionary comprehension
results = [{key:value for key,value in row.iteritems()} for row in cursor]
# Python 2.6 and before
# results = [dict((key,value) for key,value in row.iteritems()) for row in cursor]
Этот код делает тот же формат, что и версия MySQL курсора словаря, используя fetchall(). Не уверен, почему они реализовали его по-разному, но это поможет вам получить тот же результат реального словаря python, а не список в случае fetchall().