@@ -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
@@ -946,31 +947,14 @@ Connection objects
946947
947948 .. attribute :: row_factory
948949
949- A callable that accepts two arguments,
950- a :class: `Cursor ` object and the raw row results as a :class: `tuple `,
951- and returns a custom object representing an SQLite row.
952-
953- Example:
950+ The initial :attr: `~Cursor.row_factory `
951+ for :class: `Cursor ` objects created from this connection.
952+ Assigning to this attribute does not affect the :attr: `!row_factory `
953+ of existing cursors belonging to this connection, only new ones.
954+ Is ``None `` by default,
955+ meaning each row is returned as a :class: `tuple `.
954956
955- .. doctest ::
956-
957- >>> def dict_factory (cursor , row ):
958- ... col_names = [col[0 ] for col in cursor.description]
959- ... return {key: value for key, value in zip (col_names, row)}
960- >>> con = sqlite3.connect(" :memory:" )
961- >>> con.row_factory = dict_factory
962- >>> for row in con.execute(" SELECT 1 AS a, 2 AS b" ):
963- ... print (row)
964- {'a': 1, 'b': 2}
965-
966- If returning a tuple doesn't suffice and you want name-based access to
967- columns, you should consider setting :attr: `row_factory ` to the
968- highly optimized :class: `sqlite3.Row ` type. :class: `Row ` provides both
969- index-based and case-insensitive name-based access to columns with almost no
970- memory overhead. It will probably be better than your own custom
971- dictionary-based approach or even a db_row based solution.
972-
973- .. XXX what's a db_row-based solution?
957+ See :ref: `sqlite3-howto-row-factory ` for more details.
974958
975959 .. attribute :: text_factory
976960
@@ -1122,7 +1106,7 @@ Cursor objects
11221106
11231107 .. method :: fetchone()
11241108
1125- If :attr: `~Connection .row_factory ` is ``None ``,
1109+ If :attr: `~Cursor .row_factory ` is ``None ``,
11261110 return the next row query result set as a :class: `tuple `.
11271111 Else, pass it to the row factory and return its result.
11281112 Return ``None `` if no more data is available.
@@ -1216,6 +1200,22 @@ Cursor objects
12161200 including :abbr: `CTE ( Common Table Expression ) ` queries.
12171201 It is only updated by the :meth: `execute ` and :meth: `executemany ` methods.
12181202
1203+ .. attribute :: row_factory
1204+
1205+ Control how a row fetched from this :class: `!Cursor ` is represented.
1206+ If ``None ``, a row is represented as a :class: `tuple `.
1207+ Can be set to the included :class: `sqlite3.Row `;
1208+ or a :term: `callable ` that accepts two arguments,
1209+ a :class: `Cursor ` object and the :class: `!tuple ` of row values,
1210+ and returns a custom object representing an SQLite row.
1211+
1212+ Defaults to what :attr: `Connection.row_factory ` was set to
1213+ when the :class: `!Cursor ` was created.
1214+ Assigning to this attribute does not affect
1215+ :attr: `Connection.row_factory ` of the parent connection.
1216+
1217+ See :ref: `sqlite3-howto-row-factory ` for more details.
1218+
12191219
12201220.. The sqlite3.Row example used to be a how-to. It has now been incorporated
12211221 into the Row reference. We keep the anchor here in order not to break
@@ -1234,7 +1234,10 @@ Row objects
12341234 It supports iteration, equality testing, :func: `len `,
12351235 and :term: `mapping ` access by column name and index.
12361236
1237- Two row objects compare equal if have equal columns and equal members.
1237+ Two :class: `!Row ` objects compare equal
1238+ if they have identical column names and values.
1239+
1240+ See :ref: `sqlite3-howto-row-factory ` for more details.
12381241
12391242 .. method :: keys
12401243
@@ -1245,21 +1248,6 @@ Row objects
12451248 .. versionchanged :: 3.5
12461249 Added support of slicing.
12471250
1248- Example:
1249-
1250- .. doctest ::
1251-
1252- >>> con = sqlite3.connect(" :memory:" )
1253- >>> con.row_factory = sqlite3.Row
1254- >>> res = con.execute(" SELECT 'Earth' AS name, 6378 AS radius" )
1255- >>> row = res.fetchone()
1256- >>> row.keys()
1257- ['name', 'radius']
1258- >>> row[0 ], row[" name" ] # Access by index and name.
1259- ('Earth', 'Earth')
1260- >>> row[" RADIUS" ] # Column names are case-insensitive.
1261- 6378
1262-
12631251
12641252PrepareProtocol objects
12651253^^^^^^^^^^^^^^^^^^^^^^^
@@ -1855,6 +1843,96 @@ can be found in the `SQLite URI documentation`_.
18551843.. _SQLite URI documentation : https://www.sqlite.org/uri.html
18561844
18571845
1846+ .. _sqlite3-howto-row-factory :
1847+
1848+ How to create and use row factories
1849+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1850+
1851+ By default, :mod: `!sqlite3 ` represents each row as a :class: `tuple `.
1852+ If a :class: `!tuple ` does not suit your needs,
1853+ you can use the :class: `sqlite3.Row ` class
1854+ or a custom :attr: `~Cursor.row_factory `.
1855+
1856+ While :attr: `!row_factory ` exists as an attribute both on the
1857+ :class: `Cursor ` and the :class: `Connection `,
1858+ it is recommended to set :class: `Connection.row_factory `,
1859+ so all cursors created from the connection will use the same row factory.
1860+
1861+ :class: `!Row ` provides indexed and case-insensitive named access to columns,
1862+ with minimal memory overhead and performance impact over a :class: `!tuple `.
1863+ To use :class: `!Row ` as a row factory,
1864+ assign it to the :attr: `!row_factory ` attribute:
1865+
1866+ .. doctest ::
1867+
1868+ >>> con = sqlite3.connect(" :memory:" )
1869+ >>> con.row_factory = sqlite3.Row
1870+
1871+ Queries now return :class: `!Row ` objects:
1872+
1873+ .. doctest ::
1874+
1875+ >>> res = con.execute(" SELECT 'Earth' AS name, 6378 AS radius" )
1876+ >>> row = res.fetchone()
1877+ >>> row.keys()
1878+ ['name', 'radius']
1879+ >>> row[0 ] # Access by index.
1880+ 'Earth'
1881+ >>> row[" name" ] # Access by name.
1882+ 'Earth'
1883+ >>> row[" RADIUS" ] # Column names are case-insensitive.
1884+ 6378
1885+
1886+ You can create a custom :attr: `~Cursor.row_factory `
1887+ that returns each row as a :class: `dict `, with column names mapped to values:
1888+
1889+ .. testcode ::
1890+
1891+ def dict_factory(cursor, row):
1892+ fields = [column[0] for column in cursor.description]
1893+ return {key: value for key, value in zip(fields, row)}
1894+
1895+ Using it, queries now return a :class: `!dict ` instead of a :class: `!tuple `:
1896+
1897+ .. doctest ::
1898+
1899+ >>> con = sqlite3.connect(" :memory:" )
1900+ >>> con.row_factory = dict_factory
1901+ >>> for row in con.execute(" SELECT 1 AS a, 2 AS b" ):
1902+ ... print (row)
1903+ {'a': 1, 'b': 2}
1904+
1905+ The following row factory returns a :term: `named tuple `:
1906+
1907+ .. testcode ::
1908+
1909+ from collections import namedtuple
1910+
1911+ def namedtuple_factory(cursor, row):
1912+ fields = [column[0] for column in cursor.description]
1913+ cls = namedtuple("Row", fields)
1914+ return cls._make(row)
1915+
1916+ :func: `!namedtuple_factory ` can be used as follows:
1917+
1918+ .. doctest ::
1919+
1920+ >>> con = sqlite3.connect(" :memory:" )
1921+ >>> con.row_factory = namedtuple_factory
1922+ >>> cur = con.execute(" SELECT 1 AS a, 2 AS b" )
1923+ >>> row = cur.fetchone()
1924+ >>> row
1925+ Row(a=1, b=2)
1926+ >>> row[0 ] # Indexed access.
1927+ 1
1928+ >>> row.b # Attribute access.
1929+ 2
1930+
1931+ With some adjustments, the above recipe can be adapted to use a
1932+ :class: `~dataclasses.dataclass `, or any other custom class,
1933+ instead of a :class: `~collections.namedtuple `.
1934+
1935+
18581936.. _sqlite3-explanation :
18591937
18601938Explanation
0 commit comments