@@ -1320,27 +1320,11 @@ Connection objects
13201320 a :class: `Cursor ` object and the raw row results as a :class: `tuple `,
13211321 and returns a custom object representing an SQLite row.
13221322
1323- Example:
1324-
1325- .. doctest ::
1326-
1327- >>> def dict_factory (cursor , row ):
1328- ... col_names = [col[0 ] for col in cursor.description]
1329- ... return {key: value for key, value in zip (col_names, row)}
1330- >>> con = sqlite3.connect(" :memory:" )
1331- >>> con.row_factory = dict_factory
1332- >>> for row in con.execute(" SELECT 1 AS a, 2 AS b" ):
1333- ... print (row)
1334- {'a': 1, 'b': 2}
1335-
13361323 If returning a tuple doesn't suffice and you want name-based access to
13371324 columns, you should consider setting :attr: `row_factory ` to the
1338- highly optimized :class: `sqlite3.Row ` type. :class: `Row ` provides both
1339- index-based and case-insensitive name-based access to columns with almost no
1340- memory overhead. It will probably be better than your own custom
1341- dictionary-based approach or even a db_row based solution.
1325+ highly optimized :class: `sqlite3.Row `
13421326
1343- .. XXX what's a db_row-based solution?
1327+ See :ref: ` sqlite3-row-factory-how-to ` for more details.
13441328
13451329 .. attribute :: text_factory
13461330
@@ -1611,6 +1595,8 @@ Row objects
16111595
16121596 Two row objects compare equal if have equal columns and equal members.
16131597
1598+ See :ref: `sqlite3-row-factory-how-to ` for more details.
1599+
16141600 .. method :: keys
16151601
16161602 Return a :class: `list ` of column names as :class: `strings <str> `.
@@ -1620,21 +1606,6 @@ Row objects
16201606 .. versionchanged :: 3.5
16211607 Added support of slicing.
16221608
1623- Example:
1624-
1625- .. doctest ::
1626-
1627- >>> con = sqlite3.connect(" :memory:" )
1628- >>> con.row_factory = sqlite3.Row
1629- >>> res = con.execute(" SELECT 'Earth' AS name, 6378 AS radius" )
1630- >>> row = res.fetchone()
1631- >>> row.keys()
1632- ['name', 'radius']
1633- >>> row[0 ], row[" name" ] # Access by index and name.
1634- ('Earth', 'Earth')
1635- >>> row[" RADIUS" ] # Column names are case-insensitive.
1636- 6378
1637-
16381609
16391610.. _sqlite3-blob-objects :
16401611
@@ -2358,6 +2329,84 @@ can be found in the `SQLite URI documentation`_.
23582329.. _SQLite URI documentation : https://www.sqlite.org/uri.html
23592330
23602331
2332+ .. _sqlite3-row-factory-how-to :
2333+
2334+ How to work with row factories
2335+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2336+
2337+ By default, :mod: `!sqlite3 ` represent fetched rows as :class: `tuples <tuple> `.
2338+ If a :class: `!tuple ` does not suit your needs,
2339+ use the built-in :class: `Row ` type or a custom :attr: `~Connection.row_factory `.
2340+ The former provides both indexed and case-insensitive named access to columns,
2341+ with low memory overhead and minimal performance impact.
2342+ Example use:
2343+
2344+ .. doctest ::
2345+
2346+ >>> con = sqlite3.connect(" :memory:" )
2347+ >>> con.row_factory = sqlite3.Row
2348+ >>> res = con.execute(" SELECT 'Earth' AS name, 6378 AS radius" )
2349+ >>> row = res.fetchone()
2350+ >>> row.keys()
2351+ ['name', 'radius']
2352+ >>> row[0 ], row[" name" ] # Access by index and name.
2353+ ('Earth', 'Earth')
2354+ >>> row[" RADIUS" ] # Column names are case-insensitive.
2355+ 6378
2356+
2357+ If you need more flexibility, you can design your own row factory.
2358+ Here's an example of a :class: `dict ` row factory:
2359+
2360+ .. doctest ::
2361+
2362+ >>> def dict_factory (cursor , row ):
2363+ ... col_names = [col[0 ] for col in cursor.description]
2364+ ... return {key: value for key, value in zip (col_names, row)}
2365+
2366+ >>> con = sqlite3.connect(" :memory:" )
2367+ >>> con.row_factory = dict_factory
2368+ >>> for row in con.execute(" SELECT 1 AS a, 2 AS b" ):
2369+ ... print (row)
2370+ {'a': 1, 'b': 2}
2371+
2372+ Here's an example of a optimised :class: `~collections.namedtuple ` factory:
2373+
2374+ .. testcode ::
2375+
2376+ from collections import namedtuple
2377+ from functools import lru_cache
2378+
2379+ def _fields(cursor):
2380+ return [col[0] for col in cursor.description]
2381+
2382+ @lru_cache
2383+ def _make_cls(fields):
2384+ return namedtuple("Row", fields)
2385+
2386+ def NamedTupleFactory(cursor, row):
2387+ cls = _make_cls(_fields(cursor))
2388+ return cls._make(row)
2389+
2390+ Example use:
2391+
2392+ .. doctest ::
2393+
2394+ >>> con = sqlite3.connect(" :memory:" )
2395+ >>> con.row_factory = NamedTupleRow
2396+ >>> cur = con.execute(" SELECT 1 AS a, 2 AS b" )
2397+ >>> row = cur.fetchone()
2398+ >>> row
2399+ Row(a='1', b='2')
2400+ >>> row[0 ] # Indexed access.
2401+ 1
2402+ >>> row.b # Attribute access.
2403+ 2
2404+
2405+ With some adjustments, the above recipe can be adapted to use a
2406+ :class: `~dataclasses.dataclass `, or any other custom class,
2407+ instead of a :class: `~collection.namedtuple `.
2408+
2409+
23612410.. _sqlite3-explanation :
23622411
23632412Explanation
0 commit comments