Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit dffeed3

Browse files
author
Skip Montanaro
committed
Make the fieldnames argument optional in the DictReader. If self.fieldnames
is None, the next row read is used as the fieldnames. In the common case, this means the programmer doesn't need to know the fieldnames ahead of time. The first row of the file will be used. In the uncommon case, this means the programmer can set the reader's fieldnames attribute to None at any time and have the next row read as the next set of fieldnames, so a csv file can contain several "sections", each with different fieldnames.
1 parent 3bbd654 commit dffeed3

3 files changed

Lines changed: 30 additions & 6 deletions

File tree

Doc/lib/libcsv.tex

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,18 @@ \subsection{Module Contents \label{csv-contents}}
117117

118118
The \module{csv} module defines the following classes:
119119

120-
\begin{classdesc}{DictReader}{csvfile, fieldnames\optional{,
120+
\begin{classdesc}{DictReader}{csvfile\optional{,
121+
fieldnames=\constant{None},\optional{,
121122
restkey=\constant{None}\optional{,
122123
restval=\constant{None}\optional{,
123124
dialect=\code{'excel'}\optional{,
124-
fmtparam}}}}}
125+
fmtparam}}}}}}
125126
Create an object which operates like a regular reader but maps the
126-
information read into a dict whose keys are given by the \var{fieldnames}
127-
parameter. If the row read has fewer fields than the fieldnames sequence,
127+
information read into a dict whose keys are given by the optional
128+
{} \var{fieldnames}
129+
parameter. If the \var{fieldnames} parameter is omitted, the values in
130+
the first row of the \var{csvfile} will be used as the fieldnames.
131+
If the row read has fewer fields than the fieldnames sequence,
128132
the value of \var{restval} will be used as the default value. If the row
129133
read has more fields than the fieldnames sequence, the remaining data is
130134
added as a sequence keyed by the value of \var{restkey}. If the row read
@@ -149,6 +153,13 @@ \subsection{Module Contents \label{csv-contents}}
149153
to \code{'raise'} a \exception{ValueError} is raised. If it is set to
150154
\code{'ignore'}, extra values in the dictionary are ignored. All other
151155
parameters are interpreted as for \class{writer} objects.
156+
157+
Note that unlike the \class{DictReader} class, the \var{fieldnames}
158+
parameter of the \class{DictWriter} is not optional. Since Python's
159+
\class{dict} objects are not ordered, there is not enough information
160+
available to deduce the order in which the row should be written to the
161+
\var{csvfile}.
162+
152163
\end{classdesc}
153164

154165
\begin{classdesc*}{Dialect}{}

Lib/csv.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class excel_tab(excel):
9292

9393

9494
class DictReader:
95-
def __init__(self, f, fieldnames, restkey=None, restval=None,
95+
def __init__(self, f, fieldnames=None, restkey=None, restval=None,
9696
dialect="excel", *args, **kwds):
9797
self.fieldnames = fieldnames # list of keys for the dict
9898
self.restkey = restkey # key to catch long rows
@@ -104,6 +104,10 @@ def __iter__(self):
104104

105105
def next(self):
106106
row = self.reader.next()
107+
if self.fieldnames is None:
108+
self.fieldnames = row
109+
row = self.reader.next()
110+
107111
# unlike the basic reader, we prefer not to return blanks,
108112
# because we will typically wind up with a dict full of None
109113
# values

Lib/test/test_csv.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,6 @@ def test_write_escape_fieldsep(self):
382382
def test_read_escape_fieldsep(self):
383383
self.readerAssertEqual('"abc\\,def"\r\n', [['abc,def']])
384384

385-
# Disabled, pending support in csv.utils module
386385
class TestDictFields(unittest.TestCase):
387386
### "long" means the row is longer than the number of fieldnames
388387
### "short" means there are fewer elements in the row than fieldnames
@@ -401,6 +400,10 @@ def test_read_dict_fields(self):
401400
fieldnames=["f1", "f2", "f3"])
402401
self.assertEqual(reader.next(), {"f1": '1', "f2": '2', "f3": 'abc'})
403402

403+
def test_read_dict_no_fieldnames(self):
404+
reader = csv.DictReader(StringIO("f1,f2,f3\r\n1,2,abc\r\n"))
405+
self.assertEqual(reader.next(), {"f1": '1', "f2": '2', "f3": 'abc'})
406+
404407
def test_read_long(self):
405408
reader = csv.DictReader(StringIO("1,2,abc,4,5,6\r\n"),
406409
fieldnames=["f1", "f2"])
@@ -413,6 +416,12 @@ def test_read_long_with_rest(self):
413416
self.assertEqual(reader.next(), {"f1": '1', "f2": '2',
414417
"_rest": ["abc", "4", "5", "6"]})
415418

419+
def test_read_long_with_rest_no_fieldnames(self):
420+
reader = csv.DictReader(StringIO("f1,f2\r\n1,2,abc,4,5,6\r\n"),
421+
restkey="_rest")
422+
self.assertEqual(reader.next(), {"f1": '1', "f2": '2',
423+
"_rest": ["abc", "4", "5", "6"]})
424+
416425
def test_read_short(self):
417426
reader = csv.DictReader(["1,2,abc,4,5,6\r\n","1,2,abc\r\n"],
418427
fieldnames="1 2 3 4 5 6".split(),

0 commit comments

Comments
 (0)