如何从sqlite查询中获取dict?

Mel*_*oun 98 python sql sqlite dictionary dataformat

db = sqlite.connect("test.sqlite")
res = db.execute("select * from table")
Run Code Online (Sandbox Code Playgroud)

通过迭代,我得到与行相对应的列表.

for row in res:
    print row
Run Code Online (Sandbox Code Playgroud)

我可以得到列的名称

col_name_list = [tuple[0] for tuple in res.description]
Run Code Online (Sandbox Code Playgroud)

但是有一些功能或设置来获取字典而不是列表吗?

{'col1': 'value', 'col2': 'value'}
Run Code Online (Sandbox Code Playgroud)

或者我必须自己做?

Ale*_*lli 141

您可以使用row_factory,如文档中的示例所示:

import sqlite3

def dict_factory(cursor, row):
    d = {}
    for idx, col in enumerate(cursor.description):
        d[col[0]] = row[idx]
    return d

con = sqlite3.connect(":memory:")
con.row_factory = dict_factory
cur = con.cursor()
cur.execute("select 1 as a")
print cur.fetchone()["a"]
Run Code Online (Sandbox Code Playgroud)

或遵循文档中此示例后给出的建议:

如果返回一个元组是不够的,并且您希望对列进行基于名称的访问,则应考虑将row_factory设置为高度优化的sqlite3.Row类型.Row提供基于索引和不区分大小写的基于名称的访问,几乎没有内存开销.它可能比您自己的基于字典的自定义方法甚至基于db_row的解决方案更好.

  • 只是引用文档,`con.row_factory = sqlite3.Row` (68认同)

gan*_*alf 22

尽管在Adam Schmideg和Alex Martelli的回答中都部分提到了答案,但我还是回答了这个问题.为了让像我这样有其他问题的人能够轻松找到答案.

conn = sqlite3.connect(":memory:")

#This is the important part, here we are setting row_factory property of
#connection object to sqlite3.Row(sqlite3.Row is an implementation of
#row_factory)
conn.row_factory = sqlite3.Row
c = conn.cursor()
c.execute('select * from stocks')

result = c.fetchall()
#returns a list of dictionaries, each item in list(each dictionary)
#represents a row of the table
Run Code Online (Sandbox Code Playgroud)

  • 目前`fetchall()`似乎返回`sqlite3.Row`对象.然而,只需使用`dict()`:`result = [dict(row)for c.fetchall()]中的行就可以将它们转换为字典. (10认同)

bbe*_*ort 19

即使使用sqlite3.Row类 - 您仍然不能以下列形式使用字符串格式:

print "%(id)i - %(name)s: %(value)s" % row
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,我使用一个辅助函数来获取行并转换为字典.我只在字典对象优于Row对象时才使用它(例如,对于字符串格式化,其中Row对象本身也不支持字典API).但是所有其他时间都使用Row对象.

def dict_from_row(row):
    return dict(zip(row.keys(), row))       
Run Code Online (Sandbox Code Playgroud)

  • sqlite3.Row实现映射协议.你可以做`print'%(id)i - %(name)s:%(value)s"%dict(row)` (9认同)

Luk*_*ski 14

连接到 SQLite 后: con = sqlite3.connect(.....)只需运行:

con.row_factory = sqlite3.Row
Run Code Online (Sandbox Code Playgroud)

瞧!


Bas*_*asj 11

正如 @gandalf 的回答所提到的,必须使用conn.row_factory = sqlite3.Row,但结果不是直接的字典。必须dict在最后一个循环中添加额外的“转换”:

import sqlite3
conn = sqlite3.connect(":memory:")
conn.execute('create table t (a text, b text, c text)')
conn.execute('insert into t values ("aaa", "bbb", "ccc")')
conn.execute('insert into t values ("AAA", "BBB", "CCC")')
conn.row_factory = sqlite3.Row
c = conn.cursor()
c.execute('select * from t')
for r in c.fetchall():
    print(dict(r))

# {'a': 'aaa', 'b': 'bbb', 'c': 'ccc'}
# {'a': 'AAA', 'b': 'BBB', 'c': 'CCC'}
Run Code Online (Sandbox Code Playgroud)


Ign*_*ams 8

PEP 249:

Question: 

   How can I construct a dictionary out of the tuples returned by
   .fetch*():

Answer:

   There are several existing tools available which provide
   helpers for this task. Most of them use the approach of using
   the column names defined in the cursor attribute .description
   as basis for the keys in the row dictionary.

   Note that the reason for not extending the DB API specification
   to also support dictionary return values for the .fetch*()
   methods is that this approach has several drawbacks:

   * Some databases don't support case-sensitive column names or
     auto-convert them to all lowercase or all uppercase
     characters.

   * Columns in the result set which are generated by the query
     (e.g.  using SQL functions) don't map to table column names
     and databases usually generate names for these columns in a
     very database specific way.

   As a result, accessing the columns through dictionary keys
   varies between databases and makes writing portable code
   impossible.
Run Code Online (Sandbox Code Playgroud)

所以,是的,自己动手吧.


M. *_*AYA 6

较短的版本:

db.row_factory = lambda c, r: dict([(col[0], r[idx]) for idx, col in enumerate(c.description)])
Run Code Online (Sandbox Code Playgroud)


Ran*_*ssi 5

我的测试中最快:

\n\n
conn.row_factory = lambda c, r: dict(zip([col[0] for col in c.description], r))\nc = conn.cursor()\n\n%timeit c.execute('SELECT * FROM table').fetchall()\n19.8 \xc2\xb5s \xc2\xb1 1.05 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100000 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

对比:

\n\n
conn.row_factory = lambda c, r: dict([(col[0], r[idx]) for idx, col in enumerate(c.description)])\nc = conn.cursor()\n\n%timeit c.execute('SELECT * FROM table').fetchall()\n19.4 \xc2\xb5s \xc2\xb1 75.6 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 100000 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

你决定 :)

\n


Fal*_*lko 5

与前面提到的解决方案类似,但最紧凑:

db.row_factory = lambda C, R: { c[0]: R[i] for i, c in enumerate(C.description) }
Run Code Online (Sandbox Code Playgroud)