DictCursor似乎不适用于psycopg2

时间:2011-07-18 20:59:49

标签: python postgresql dictionary psycopg2

之前我没有使用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变量总是一个列表,而不是我期望的字典。

我实现的当前解决方法是使用此函数构建字典并运行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。

6 个答案:

答案 0 :(得分:88)

使用RealDictCursor:

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

这为您提供了一个列表,其中行为真正的python词典,而不是“高级psycopg2列表”。

答案 1 :(得分:26)

res = cur.fetchall()

使res成为psycopg2.extras.DictRow的列表。


或者,您可以利用cur.fetchall是可迭代的事实,而不是调用cur

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

因此您将能够使用dict语法访问数据。

答案 2 :(得分:6)

另一个解决方案是使用Named Tuple Cursor,因为Real Dict Cursor会破坏任何使用整数指标的查询,如文档中所述。

使用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

这样可以保持整洁,并且就我所知而言不会破坏任何东西。

答案 3 :(得分:3)

虽然这是一个较旧的问题,但它仍会出现在谷歌中,所以我想我会为其他来自大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;")

虽然这是在y循环中使用for x,但就我所知,它的pythonic ......希望这对那里的某些人有帮助。

答案 4 :(得分:0)

除了使用RealDictCursor功能外,您可能还需要询问所有列 (在选择后使用*符号),如答案中所述。

我对结果的某些列不感兴趣,因为它们具有已知值 已在WHERE条件中使用。但是SELECT (..., ..., ..., ...) FROM ... WHERE ... 变体没有给我字典。

祝你好运! 哈利

答案 5 :(得分:0)

因此,要使其工作类似于Dictionary游标的mysql版本,您必须将其包装在另一个函数或代码中。我将继续在论坛上向他们建议这些代码,以便在fetchall()调用与Dictionary Cursor一起使用时返回字典。以下是一些可用于修复它的示例代码:

 Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC_FOR_XE)))
    STATUS of the LISTENER
    ------------------------
    Alias                     LISTENER
    Version                   TNSLSNR for Linux: Version 11.2.0.2.0 - Production
    Start Date                28-DEC-2017 15:51:21
    Uptime                    0 days 2 hr. 8 min. 36 sec
    Trace Level               off
    Security                  ON: Local OS Authentication
    SNMP                      OFF
    Default Service           XE
    Listener Parameter File   /u01/app/oracle/product/11.2.0/xe/network/admin/listener.ora
    Listener Log File         /u01/app/oracle/diag/tnslsnr/e48c7c272f44/listener/alert/log.xml
    Listening Endpoints Summary...
      (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_XE)))
      (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=e48c7c272f44)(PORT=1521)))
      (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=e48c7c272f44)(PORT=8080))(Presentation=HTTP)(Session=RAW))
    Services Summary...
    Service "PLSExtProc" has 1 instance(s).
      Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
    Service "XE" has 1 instance(s).
      Instance "XE", status READY, has 1 handler(s) for this service...
    Service "XEXDB" has 1 instance(s).
      Instance "XE", status READY, has 1 handler(s) for this service...
     here its my listener status

此代码使用与fetchall()的字典光标的MySQL版本相同的格式。不确定为什么他们以不同的方式实现它,但这将帮助您获得实际python字典的相同输出,而不是fetchall()情况下的列表。