Index: Doc/library/csv.rst =================================================================== --- Doc/library/csv.rst (revision 59940) +++ Doc/library/csv.rst (working copy) @@ -161,7 +161,19 @@ The :mod:`csv` module defines the following classes: +.. class:: NamedTupleReader(csvfile, namedtuple[, restkey=None[, restval=None[, dialect='excel'[, *args, **kwds]]]]) + Create an object which operates like a regular reader but maps the information + read into a *namedtuple* whose fields can be accessed using attribute lookup. + If *namedtuple* is a string, then it will be used as the typename and + the values in the first row of the *csvfile* will be used as the fieldnames. + If the row read has fewer fields than the fieldnames sequence, the value of + *restval* will be used as the default value. If the row read has more fields + than the fieldnames sequence, then the extra fields will be clipped unless + *restkey* has been specified. If it is has, then the extra fields are stored + as a single list in the last field, named is *restkey*. Any other optional or + keyword arguments are passed to the underlying :class:`reader` instance. + .. class:: DictReader(csvfile[, fieldnames=None[, restkey=None[, restval=None[, dialect='excel'[, *args, **kwds]]]]]) Create an object which operates like a regular reader but maps the information Index: Lib/csv.py =================================================================== --- Lib/csv.py (revision 59940) +++ Lib/csv.py (working copy) @@ -10,6 +10,7 @@ QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE, \ __doc__ from _csv import Dialect as _Dialect +from collections import namedtuple as _namedtuple try: from cStringIO import StringIO @@ -67,7 +68,31 @@ delimiter = '\t' register_dialect("excel-tab", excel_tab) +def NamedTupleReader(f, namedtuple, restkey=None, restval=None, dialect="excel", *args, **kwds): + + if isinstance(namedtuple, basestring): + typename = namedtuple + namedtuple = None + n = 0 + else: + n = len(namedtuple._fields) + for row in reader(f, dialect, *args, **kwds): + if namedtuple is None: + n = len(row) + namedtuple = _namedtuple(typename, row + [restkey]) + continue + if not row: # skip blank inputs + continue + if len(row) < n: # pad missing fields with restval + row += [restval] * (n - len(row)) + if restkey is None: # either clip or assign to restkey + row = row[:n] + else: + row[n:] = [row[n:]] + yield namedtuple._make(row) + + class DictReader: def __init__(self, f, fieldnames=None, restkey=None, restval=None, dialect="excel", *args, **kwds):