The one solution in the comment, suggesting to use a dictionary row factory, seems very close to what you want.
Even closer (as easier to write) seems to me a namedtuple
. For this purpose, I once wrote this:
def namtupiter(c):
from collections import namedtuple
fields = tuple(i[0] for i in c.description)
Row = namedtuple('Row', fields)
# make Row a tuple and a "dict" (well, kind of...) at the same time.
# Don't lose tuple property, so only process strings and pass everything
# other to super().
Row.__getitem__ = lambda self, item: getattr(self, item) if isinstance(item, basestring) else super(Row, self).__getitem__(item)
for i in c:
try:
# try to access i as a dict
yield Row(*(i[f] for f in fields))
except TypeError:
# it is no dict -> try tuple
yield Row(*i)
class CursorNTRowsMixIn(object):
_fetch_type = 0 # tuples
def _do_get_result(self):
super(CursorNTRowsMixIn, self)._do_get_result()
# create a named tuple class
from collections import namedtuple
if self.description:
self.RowClass = namedtuple('Row', tuple(i[0] for i in self.description))
def _fetch_row(self, size=1):
rows = super(CursorNTRowsMixIn, self)._fetch_row(size)
# turn every row into a Row().
return tuple(self.RowClass(*i) for i in rows)
class NTCursor(CursorStoreResultMixIn, CursorNTRowsMixIn,
BaseCursor):
pass
class SSNTCursor(CursorUseResultMixIn, CursorNTRowsMixIn,
BaseCursor):
pass
With the namtupiter()
, you can iterate over a cursor containing a resultset and receive NamedTuples with the DB fields contained as attributes.
So you can do
for r in namtupiter(db.select(fields=('id', 'name', 'area', _from='sometable', where='area IS NOT NULL')):
print r.id, r.name, r.area
Another way is the (SS
)NTCursor
which can be seen as an alternative to the existing cursors which provide tuples or dicts. These new cursors as well provide the rows as named tuples with the name information extracted from the result set.