DictCursor在psycopg2下似乎无效

78 投票
6 回答
73286 浏览
提问于 2025-04-16 21:47

我之前没有用过psycopg2这个库,但我想把光标工厂改成DictCursor,这样用fetchall或fetchone的时候就能返回字典,而不是列表。

我写了一个测试脚本,目的是简单测试这个功能。以下是我觉得应该能工作的代码:

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这个变量总是返回一个列表,而不是我期待的字典。

目前我找到的一个解决办法是使用一个函数,这个函数可以把返回的每一行数据转换成字典。

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。

6 个回答

19

另一种解决方案是使用命名元组游标,因为真实字典游标会导致任何使用整数索引的查询出错,具体情况可以在它的文档中找到。

使用命名元组游标时,你可以像这样用点语法来访问它们:

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

这样可以保持代码整洁,并且据我所知不会出错。

141

使用 RealDictCursor

import psycopg2.extras

cur = conn.cursor(cursor_factory = psycopg2.extras.RealDictCursor)
cur.execute("SELECT * from review")
res = cur.fetchall()    

这样你就能得到一个列表,里面的每一行都是标准的 Python 字典,而不是“复杂的 psycopg2 列表”。

45
res = cur.fetchall()

这段代码让 res 变成一个包含 psycopg2.extras.DictRow 的列表。


另外,你可以不调用 cur.fetchall,而是利用 cur 是一个可迭代对象的特点:

cur.execute("SELECT * from review")
for row in cur:
    print(row['column_name'])

这样你就可以用类似字典的方式来访问数据。

撰写回答