我正在使用sqlite3的python API,我有一个用于存储语言的小表,其中包含id,name和creation_date字段。我正试图按照文档的建议将原始查询结果Map到namedtuple
中,这样我就可以以更可读的方式管理行,所以这里是我的namedtuple
。
LanguageRecord = namedtuple('LanguageRecord', 'id, name, creation_date')
文档建议的Map代码如下:
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
约束来设置name字段,以便只保证一个结果。
for language in map(LanguageRecord._make, c.fetchall()):
# do something with languages
另一种方法可以使用fetchall()[0]
而不使用unique
约束来保证只得到一个结果。
我的问题是,哪一种是处理这个问题的最好和最常用的方法,我应该总是使用fetchall
来维护一个公共接口,让数据库管理唯一性逻辑吗?或者我应该像方法1那样显式地创建一个列表?有没有更简单的方法来完成这项任务?
5条答案
按热度按时间oxf4rvwz1#
有一个更简单的方法!Sqlite3为用户提供了一种定义“行工厂”的方法。这些行工厂接受游标和元组行,并可以返回任何类型的对象。
一旦将行工厂设置为
则游标返回的行将是应用于元组行的
my_row_factory
的结果。比如说,收益率
有关如何定义namedtuple工厂的另一个示例,请参见this post。
顺便说一下,如果你设置
然后行作为字典返回,字典的键是表的列名。因此,您可以使用内置的
sqlite3.Row
行工厂并使用row['creation_date']
访问等效的行工厂,而不是使用row.creation_date
访问namedtuple的部分。pnwntuvh2#
一个改进的
row_factory
实际上是这样的,它可以被重用于所有类型的查询:gr8qqesn3#
在
namedtuple
上面还有一个row_factory
:为了使用其他类工厂,可以进一步泛化:
当所有查询结果都具有相同的字段时,这些工厂函数非常有用。
示例如下:
namedtuple_factory = make_row_factory(namedtuple)
import dataclass
row_factory = make_row_factory(dataclass.make_dataclass)
pip3 install recordclass
import recordclass
row_factory = make_row_factory(recordclass.make_dataclass, fast_new=True)
这里有一些性能计数器来比较不同的方法(debian Linux,64位,python 3.9)。
用于创建测试数据库的脚本:
预设值:
sqlite3.Row:
命名元组:
基于命名元组的行工厂:
记录类:
基于记录类的行工厂:
lnvxswe24#
我演示了如何从SQL查询中获取结果框架并将其转换为namedtuple列表。我没有动态地将数组列绑定到nametuple名称,不确定这是否可行。
产出:
nr9pn0ug5#
我认为最好使用
for language in map(LanguageRecord._make, c.fetchall()[:1]):
,因为它可能会导致fetchall()[0]的IndexError。如果你只需要一个结果,而查询中已经有了“WHERE”。据我所知,查询应该返回一行。早期优化是邪恶的。:)