Keywords: Python | SQLite | dictionary | data_format | row_factory
Abstract: This article explains how to convert SQLite query results from lists to dictionaries by setting the row_factory attribute, covering two methods: custom functions and the built-in sqlite3.Row class, with a comparison of their advantages.
When using the Python sqlite3 module for database operations, query results are typically returned as a list of tuples, each representing a row of data. However, in some scenarios, it is desirable to access data in dictionary format, where keys are column names and values are corresponding data. This can be achieved by setting the row_factory attribute of the connection object, avoiding the need for manual conversion.
Custom Row Factory Function
One approach is to define a custom function that converts cursor descriptions and row data into dictionaries. The implementation iterates over the cursor's column descriptions, using column names as keys and row values as values to build a dictionary object. Example code demonstrates how to set row_factory to a custom function and execute queries to obtain results in dictionary format.
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"])
This method offers flexibility in customizing the dictionary structure but may introduce additional overhead. For performance-sensitive applications, more optimized solutions should be considered.
Using the Built-in sqlite3.Row Class
A more efficient alternative is to use the built-in sqlite3.Row class. The Row class is highly optimized, with minimal memory overhead, and allows access to data via indices or column names, supporting case-insensitive column name access. By setting row_factory to sqlite3.Row, query results return Row objects that provide a dictionary-like interface for easy manipulation.
import sqlite3
con = sqlite3.connect(":memory:")
con.row_factory = sqlite3.Row
cursor = con.cursor()
cursor.execute('select * from stocks')
result = cursor.fetchall() # Returns a list where each element is a Row object, accessible like a dictionary
Using the Row class is generally preferable to custom functions, as it is implemented in C for faster access and is recommended in the documentation.
Comparison and Recommendations
The custom dict_factory function provides flexibility, suitable for scenarios requiring special data processing, such as filtering or transforming specific columns. However, the sqlite3.Row class excels in performance, particularly when handling large datasets, by reducing memory usage and improving access speed. Therefore, in most cases, it is advisable to use the built-in Row class. If a project demands specific dictionary formats, one might combine both approaches, for example, by processing Row objects further.
In summary, by appropriately configuring row_factory, it is straightforward to convert SQLite query results into dictionaries, enhancing code readability and maintainability while balancing performance needs. In practice, the choice of method should be based on the specific requirements of the application.