@@ -239,6 +239,7 @@ inserted data and retrieved values from it in multiple ways.
239239 * :ref: `sqlite3-adapters `
240240 * :ref: `sqlite3-converters `
241241 * :ref: `sqlite3-connection-context-manager `
242+ * :ref: `sqlite3-howto-row-factory `
242243
243244 * :ref: `sqlite3-explanation ` for in-depth background on transaction control.
244245
@@ -1236,31 +1237,14 @@ Connection objects
12361237
12371238 .. attribute :: row_factory
12381239
1239- A callable that accepts two arguments,
1240- a :class: `Cursor ` object and the raw row results as a :class: `tuple `,
1241- and returns a custom object representing an SQLite row.
1242-
1243- Example:
1240+ The initial :attr: `~Cursor.row_factory `
1241+ for :class: `Cursor ` objects created from this connection.
1242+ Assigning to this attribute does not affect the :attr: `!row_factory `
1243+ of existing cursors belonging to this connection, only new ones.
1244+ Is ``None `` by default,
1245+ meaning each row is returned as a :class: `tuple `.
12441246
1245- .. doctest ::
1246-
1247- >>> def dict_factory (cursor , row ):
1248- ... col_names = [col[0 ] for col in cursor.description]
1249- ... return {key: value for key, value in zip (col_names, row)}
1250- >>> con = sqlite3.connect(" :memory:" )
1251- >>> con.row_factory = dict_factory
1252- >>> for row in con.execute(" SELECT 1 AS a, 2 AS b" ):
1253- ... print (row)
1254- {'a': 1, 'b': 2}
1255-
1256- If returning a tuple doesn't suffice and you want name-based access to
1257- columns, you should consider setting :attr: `row_factory ` to the
1258- highly optimized :class: `sqlite3.Row ` type. :class: `Row ` provides both
1259- index-based and case-insensitive name-based access to columns with almost no
1260- memory overhead. It will probably be better than your own custom
1261- dictionary-based approach or even a db_row based solution.
1262-
1263- .. XXX what's a db_row-based solution?
1247+ See :ref: `sqlite3-howto-row-factory ` for more details.
12641248
12651249 .. attribute :: text_factory
12661250
@@ -1413,7 +1397,7 @@ Cursor objects
14131397
14141398 .. method :: fetchone()
14151399
1416- If :attr: `~Connection .row_factory ` is ``None ``,
1400+ If :attr: `~Cursor .row_factory ` is ``None ``,
14171401 return the next row query result set as a :class: `tuple `.
14181402 Else, pass it to the row factory and return its result.
14191403 Return ``None `` if no more data is available.
@@ -1507,6 +1491,22 @@ Cursor objects
15071491 including :abbr: `CTE ( Common Table Expression ) ` queries.
15081492 It is only updated by the :meth: `execute ` and :meth: `executemany ` methods.
15091493
1494+ .. attribute :: row_factory
1495+
1496+ Control how a row fetched from this :class: `!Cursor ` is represented.
1497+ If ``None ``, a row is represented as a :class: `tuple `.
1498+ Can be set to the included :class: `sqlite3.Row `;
1499+ or a :term: `callable ` that accepts two arguments,
1500+ a :class: `Cursor ` object and the :class: `!tuple ` of row values,
1501+ and returns a custom object representing an SQLite row.
1502+
1503+ Defaults to what :attr: `Connection.row_factory ` was set to
1504+ when the :class: `!Cursor ` was created.
1505+ Assigning to this attribute does not affect
1506+ :attr: `Connection.row_factory ` of the parent connection.
1507+
1508+ See :ref: `sqlite3-howto-row-factory ` for more details.
1509+
15101510
15111511.. The sqlite3.Row example used to be a how-to. It has now been incorporated
15121512 into the Row reference. We keep the anchor here in order not to break
@@ -1525,7 +1525,10 @@ Row objects
15251525 It supports iteration, equality testing, :func: `len `,
15261526 and :term: `mapping ` access by column name and index.
15271527
1528- Two row objects compare equal if have equal columns and equal members.
1528+ Two :class: `!Row ` objects compare equal
1529+ if they have identical column names and values.
1530+
1531+ See :ref: `sqlite3-howto-row-factory ` for more details.
15291532
15301533 .. method :: keys
15311534
@@ -1536,21 +1539,6 @@ Row objects
15361539 .. versionchanged :: 3.5
15371540 Added support of slicing.
15381541
1539- Example:
1540-
1541- .. doctest ::
1542-
1543- >>> con = sqlite3.connect(" :memory:" )
1544- >>> con.row_factory = sqlite3.Row
1545- >>> res = con.execute(" SELECT 'Earth' AS name, 6378 AS radius" )
1546- >>> row = res.fetchone()
1547- >>> row.keys()
1548- ['name', 'radius']
1549- >>> row[0 ], row[" name" ] # Access by index and name.
1550- ('Earth', 'Earth')
1551- >>> row[" RADIUS" ] # Column names are case-insensitive.
1552- 6378
1553-
15541542
15551543.. _sqlite3-blob-objects :
15561544
@@ -2241,6 +2229,96 @@ can be found in the `SQLite URI documentation`_.
22412229.. _SQLite URI documentation : https://www.sqlite.org/uri.html
22422230
22432231
2232+ .. _sqlite3-howto-row-factory :
2233+
2234+ How to create and use row factories
2235+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2236+
2237+ By default, :mod: `!sqlite3 ` represents each row as a :class: `tuple `.
2238+ If a :class: `!tuple ` does not suit your needs,
2239+ you can use the :class: `sqlite3.Row ` class
2240+ or a custom :attr: `~Cursor.row_factory `.
2241+
2242+ While :attr: `!row_factory ` exists as an attribute both on the
2243+ :class: `Cursor ` and the :class: `Connection `,
2244+ it is recommended to set :class: `Connection.row_factory `,
2245+ so all cursors created from the connection will use the same row factory.
2246+
2247+ :class: `!Row ` provides indexed and case-insensitive named access to columns,
2248+ with minimal memory overhead and performance impact over a :class: `!tuple `.
2249+ To use :class: `!Row ` as a row factory,
2250+ assign it to the :attr: `!row_factory ` attribute:
2251+
2252+ .. doctest ::
2253+
2254+ >>> con = sqlite3.connect(" :memory:" )
2255+ >>> con.row_factory = sqlite3.Row
2256+
2257+ Queries now return :class: `!Row ` objects:
2258+
2259+ .. doctest ::
2260+
2261+ >>> res = con.execute(" SELECT 'Earth' AS name, 6378 AS radius" )
2262+ >>> row = res.fetchone()
2263+ >>> row.keys()
2264+ ['name', 'radius']
2265+ >>> row[0 ] # Access by index.
2266+ 'Earth'
2267+ >>> row[" name" ] # Access by name.
2268+ 'Earth'
2269+ >>> row[" RADIUS" ] # Column names are case-insensitive.
2270+ 6378
2271+
2272+ You can create a custom :attr: `~Cursor.row_factory `
2273+ that returns each row as a :class: `dict `, with column names mapped to values:
2274+
2275+ .. testcode ::
2276+
2277+ def dict_factory(cursor, row):
2278+ fields = [column[0] for column in cursor.description]
2279+ return {key: value for key, value in zip(fields, row)}
2280+
2281+ Using it, queries now return a :class: `!dict ` instead of a :class: `!tuple `:
2282+
2283+ .. doctest ::
2284+
2285+ >>> con = sqlite3.connect(" :memory:" )
2286+ >>> con.row_factory = dict_factory
2287+ >>> for row in con.execute(" SELECT 1 AS a, 2 AS b" ):
2288+ ... print (row)
2289+ {'a': 1, 'b': 2}
2290+
2291+ The following row factory returns a :term: `named tuple `:
2292+
2293+ .. testcode ::
2294+
2295+ from collections import namedtuple
2296+
2297+ def namedtuple_factory(cursor, row):
2298+ fields = [column[0] for column in cursor.description]
2299+ cls = namedtuple("Row", fields)
2300+ return cls._make(row)
2301+
2302+ :func: `!namedtuple_factory ` can be used as follows:
2303+
2304+ .. doctest ::
2305+
2306+ >>> con = sqlite3.connect(" :memory:" )
2307+ >>> con.row_factory = namedtuple_factory
2308+ >>> cur = con.execute(" SELECT 1 AS a, 2 AS b" )
2309+ >>> row = cur.fetchone()
2310+ >>> row
2311+ Row(a=1, b=2)
2312+ >>> row[0 ] # Indexed access.
2313+ 1
2314+ >>> row.b # Attribute access.
2315+ 2
2316+
2317+ With some adjustments, the above recipe can be adapted to use a
2318+ :class: `~dataclasses.dataclass `, or any other custom class,
2319+ instead of a :class: `~collections.namedtuple `.
2320+
2321+
22442322.. _sqlite3-explanation :
22452323
22462324Explanation
0 commit comments