关于数据库:Sqlite和Python —使用fetchone()返回字典吗?

Sqlite and Python — return a dictionary using fetchone()?

我正在python 2.5中使用sqlite3。我创建了一个看起来像这样的表:

1
2
3
4
   create table votes (
      bill text,
      senator_id text,
      vote text)

我正在使用类似这样的内容进行访问:

1
2
3
4
5
v_cur.execute("select * from votes")
row = v_cur.fetchone()
bill = row[0]
senator_id = row[1]
vote = row[2]

我想做的是让fetchone(或其他方法)返回字典,而不是列表,以便我可以按名称而不是位置来引用该字段。例如:

1
2
3
bill = row['bill']
senator_id = row['senator_id']
vote = row['vote']

我知道您可以使用MySQL执行此操作,但是有人知道如何使用SQLite进行操作吗?

谢谢!!!


在sqlite3中实际上有一个选项。将连接对象的row_factory成员更改为sqlite3.Row

1
conn = sqlite3.connect('db', row_factory=sqlite3.Row)

1
conn.row_factory = sqlite3.Row

这将允许您按名称(字典样式)或按索引访问行元素。这比创建自己的解决方法要有效得多。


我过去这样做的方式:

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

然后您在连接中进行设置:

1
2
3
from pysqlite2 import dbapi2 as sqlite
conn = sqlite.connect(...)
conn.row_factory = dict_factory

这在pysqlite-2.4.1和python 2.5.4下有效。


我最近在尝试使用sqlite3.Row()时做类似的事情。虽然sqlite3.Row()非常适合提供类似于字典的接口或类似于元组的接口,但是当我使用** kwargs在行中进行管道传输时,它不起作用。因此,需要一种将其转换为字典的快速方法。我意识到,只需使用itertools,就可以将Row()对象转换为字典。

Python 2:

1
2
3
4
5
6
db.row_factory = sqlite3.Row
dbCursor = db.cursor()
dbCursor.execute("SELECT * FROM table")
row = dbCursor.fetchone()

rowDict = dict(itertools.izip(row.keys(), row))

或者在Python 3中更简单:

1
2
3
4
dbCursor = db.cursor()
dbCursor.execute("SELECT * FROM table")
row = dbCursor.fetchone()
rowDict = dict(zip([c[0] for c in dbCursor.description], row))

类似地,您可以使用dbCursor.fetchall()命令并将整个行集转换为for循环中的词典列表。


当然,请按照http://trac.edgewall.org/pysqlite.org-mirror/wiki/PysqliteFactories中的说明和说明,使自己成为DictConnection和DictCursor。


我知道您不是在问这个问题,但是为什么不仅仅使用sqlalchemy为数据库建立一个orm?那么你可以做类似的事情,

1
2
entry = model.Session.query(model.Votes).first()
print entry.bill, entry.senator_id, entry.vote

作为一项额外的奖励,您的代码将可以轻松地移植到备用数据库中,并且免费管理连接和其他内容。


简单的解决方案,初始化一个游标对象:

1
cursor = conn.cursor(buffered = True, dictionary = True)

另一个选项:

1
cursor = conn.cursor(MySQLdb.cursors.DictCursor)

其余代码:

1
2
3
query ="SELECT * FROM table"
cursor.execute(query)
row = cursor.fetchone()

来源:mysql.connector.cursor,MySQLdb.cursors.DictCursor


我已经使用过:

1
2
def get_dict(sql):
    return dict(c.execute(sql,()).fetchall())

然后您可以执行以下操作:

1
2
c = conn.cursor()
d = get_dict("select user,city from vals where user like 'a%'");

现在d是一个字典,其中的键是user,值是city。这也适用于group by


我使用类似这样的东西:

1
2
3
4
5
6
7
8
9
10
class SqliteRow(object):
    def __init__(self):
        self.fields = []

    def add_field(self, name, value):
        self.fields.append(name)
        setattr(self, name, value)

    def to_tuple(self):
        return tuple([getattr(self, x) for x in self.fields])

与此:

1
2
3
4
5
6
7
def myobject_factory(cursor, row):
    myobject= MyObject()
    for idx, col in enumerate(cursor.description):
        name, value = (col[0], row[idx])

        myobject.add_field(name, value)
    return myobject

MyObject()是从SqliteRow继承的类。
SqliteRow类是查询要返回的每个对象的基类。
每列都将成为一个属性,并记录到fields列表中。
函数to_tuple用于将整个对象更改为适合查询的形式(只需传递整个对象而忘记)。

获取该函数的不同类类型。您需要创建一个工厂对象,该工厂对象将基于字段列表生成对象(例如:带有{some_unique_value_made_of_fields:class}的dict)

这样,我得到一个简单的ORM。