Подтвердить что ты не робот

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.

4b9b3361

Ответ 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().