测绘结果行Python中的SQLite namedtuple(Mapping result rows

2019-09-01 17:23发布

我玩了一下使用Python API的sqlite3的,我有店面语言一张小桌子与ID,姓名和CREATION_DATE领域。 我试图映射原始查询结果为namedtuple作为文档推荐,这种方式我可以在一个更可读的方式管理行,所以这里是我的namedtuple

LanguageRecord = namedtuple('LanguageRecord', 'id, name, creation_date')

该文档建议该映射的代码如下:

for language in map(LanguageRecord._make, c.fetchall()):
  # do something with languages

这是罚款时,我要回的语言,但在这种情况下,我只想找回一种语言的集合:

c.execute('SELECT * FROM language WHERE name=?', (name,))

所以,我的第一次尝试是这样的:

language = map(LanguageRecord._make, c.fetchone())

此代码不工作,因为fetchone()返回一个元组,而不是一个元组的列表,所以map函数试图创建三个namedtuples一个每个元组领域的思想。

我的第一个解决这个方法是明确创建一个列表,并追加到它的元组的结果,是这样的:

languages = []
languages.append(c.fetchone())
for language in map(LanguageRecord._make, languages):
  # do something with language

我的第二个方法是使用fetchall()虽然我只想要一个记录。 我可以用一组名称字段unique ,才能在数据库约束到garantize只是一个结果。

for language in map(LanguageRecord._make, c.fetchall()):
  # do something with languages

另一种方法可以是使用fetchall()[0]而不unique约束到garantize只是一个结果。

我的问题是这是解决这个问题最好的和常见的方式,我应该用始终fetchall保持一个通用的接口,让数据库管理的独特逻辑是什么? 或者我应该明确地创建一个列表,在方法上1? 有没有更简单的方法来完成这项任务?

Answer 1:

还有一个更简单的方法! SQLITE3为用户定义的方式“行工厂” 。 这些排工厂采取光标和元组行可以返回它想要的任何类型的对象。

一旦你设置行工厂

con.row_factory = my_row_factory

然后用光标返回的行会的结果my_row_factory施加到元组行。 例如,

import sqlite3
import collections

LanguageRecord = collections.namedtuple('LanguageRecord', 'id name creation_date')
def namedtuple_factory(cursor, row):
    return LanguageRecord(*row)

con = sqlite3.connect(":memory:")
con.row_factory = namedtuple_factory
cur = con.cursor()
cur.execute("select 1,2,3")
print(cur.fetchone())

产量

LanguageRecord(id=1, name=2, creation_date=3)

对于如何定义namedtuple工厂另一个例子,看到这个帖子 。


顺便说一句,如果你设置

conn.row_factory = sqlite3.Row

然后行返回类型的字典,它的键是表的列名。 因此,而不是访问的东西,如namedtuple的部分row.creation_date你可以只使用内置的sqlite3.Row排工厂,并与访问相当于row['creation_date']



Answer 2:

改进row_factory其实这是,它可以用于各种查询的可重复使用:

from collections import namedtuple

def namedtuple_factory(cursor, row):
    """Returns sqlite rows as named tuples."""
    fields = [col[0] for col in cursor.description]
    Row = namedtuple("Row", fields)
    return Row(*row)

conn = sqlite3.connect(":memory:")
conn.row_factory = namedtuple_factory
cur = con.cursor()


Answer 3:

我认为最好使用for language in map(LanguageRecord._make, c.fetchall()[:1]):因为它可能会导致IndexError与使用fetchall()[0]。

如果你需要一个结果,并且已经有“WHERE”中查询。 据我了解查询应返回一行。 早期的优化是邪恶的。 :)



文章来源: Mapping result rows to namedtuple in python sqlite