summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/lib/libcsv.tex19
-rw-r--r--Lib/csv.py6
-rw-r--r--Lib/test/test_csv.py11
3 files changed, 30 insertions, 6 deletions
diff --git a/Doc/lib/libcsv.tex b/Doc/lib/libcsv.tex
index e2877ee..bf8b0bf 100644
--- a/Doc/lib/libcsv.tex
+++ b/Doc/lib/libcsv.tex
@@ -117,14 +117,18 @@ Return the names of all registered dialects.
The \module{csv} module defines the following classes:
-\begin{classdesc}{DictReader}{csvfile, fieldnames\optional{,
+\begin{classdesc}{DictReader}{csvfile\optional{,
+ fieldnames=\constant{None},\optional{,
restkey=\constant{None}\optional{,
restval=\constant{None}\optional{,
dialect=\code{'excel'}\optional{,
- fmtparam}}}}}
+ fmtparam}}}}}}
Create an object which operates like a regular reader but maps the
-information read into a dict whose keys are given by the \var{fieldnames}
-parameter. If the row read has fewer fields than the fieldnames sequence,
+information read into a dict whose keys are given by the optional
+{} \var{fieldnames}
+parameter. If the \var{fieldnames} parameter is omitted, the values in
+the first row of the \var{csvfile} will be used as the fieldnames.
+If the row read has fewer fields than the fieldnames sequence,
the value of \var{restval} will be used as the default value. If the row
read has more fields than the fieldnames sequence, the remaining data is
added as a sequence keyed by the value of \var{restkey}. If the row read
@@ -149,6 +153,13 @@ method contains a key not found in \var{fieldnames}, the optional
to \code{'raise'} a \exception{ValueError} is raised. If it is set to
\code{'ignore'}, extra values in the dictionary are ignored. All other
parameters are interpreted as for \class{writer} objects.
+
+Note that unlike the \class{DictReader} class, the \var{fieldnames}
+parameter of the \class{DictWriter} is not optional. Since Python's
+\class{dict} objects are not ordered, there is not enough information
+available to deduce the order in which the row should be written to the
+\var{csvfile}.
+
\end{classdesc}
\begin{classdesc*}{Dialect}{}
diff --git a/Lib/csv.py b/Lib/csv.py
index 096badc..f2389fd 100644
--- a/Lib/csv.py
+++ b/Lib/csv.py
@@ -92,7 +92,7 @@ register_dialect("excel-tab", excel_tab)
class DictReader:
- def __init__(self, f, fieldnames, restkey=None, restval=None,
+ def __init__(self, f, fieldnames=None, restkey=None, restval=None,
dialect="excel", *args, **kwds):
self.fieldnames = fieldnames # list of keys for the dict
self.restkey = restkey # key to catch long rows
@@ -104,6 +104,10 @@ class DictReader:
def next(self):
row = self.reader.next()
+ if self.fieldnames is None:
+ self.fieldnames = row
+ row = self.reader.next()
+
# unlike the basic reader, we prefer not to return blanks,
# because we will typically wind up with a dict full of None
# values
diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py
index d85c5b6..29a13cb 100644
--- a/Lib/test/test_csv.py
+++ b/Lib/test/test_csv.py
@@ -382,7 +382,6 @@ class TestQuotedEscapedExcel(TestCsvBase):
def test_read_escape_fieldsep(self):
self.readerAssertEqual('"abc\\,def"\r\n', [['abc,def']])
-# Disabled, pending support in csv.utils module
class TestDictFields(unittest.TestCase):
### "long" means the row is longer than the number of fieldnames
### "short" means there are fewer elements in the row than fieldnames
@@ -401,6 +400,10 @@ class TestDictFields(unittest.TestCase):
fieldnames=["f1", "f2", "f3"])
self.assertEqual(reader.next(), {"f1": '1', "f2": '2', "f3": 'abc'})
+ def test_read_dict_no_fieldnames(self):
+ reader = csv.DictReader(StringIO("f1,f2,f3\r\n1,2,abc\r\n"))
+ self.assertEqual(reader.next(), {"f1": '1', "f2": '2', "f3": 'abc'})
+
def test_read_long(self):
reader = csv.DictReader(StringIO("1,2,abc,4,5,6\r\n"),
fieldnames=["f1", "f2"])
@@ -413,6 +416,12 @@ class TestDictFields(unittest.TestCase):
self.assertEqual(reader.next(), {"f1": '1', "f2": '2',
"_rest": ["abc", "4", "5", "6"]})
+ def test_read_long_with_rest_no_fieldnames(self):
+ reader = csv.DictReader(StringIO("f1,f2\r\n1,2,abc,4,5,6\r\n"),
+ restkey="_rest")
+ self.assertEqual(reader.next(), {"f1": '1', "f2": '2',
+ "_rest": ["abc", "4", "5", "6"]})
+
def test_read_short(self):
reader = csv.DictReader(["1,2,abc,4,5,6\r\n","1,2,abc\r\n"],
fieldnames="1 2 3 4 5 6".split(),