diff -r b04560c3ce69 Doc/library/csv.rst --- a/Doc/library/csv.rst Wed Aug 03 22:02:42 2016 -0700 +++ b/Doc/library/csv.rst Sat Aug 27 01:26:22 2016 +0800 @@ -150,18 +150,25 @@ dialect='excel', *args, **kwds) Create an object which operates like a regular reader but maps the - information read into a dict whose keys are given by the optional - *fieldnames* parameter. The *fieldnames* parameter is a :mod:`sequence - ` whose elements are associated with the fields of the + information read into an :mod:`OrderedDict ` + whose keys are given by the optional *fieldnames* parameter. + The *fieldnames* parameter is a :mod:`sequence ` + whose elements are associated with the fields of the input data in order. These elements become the keys of the resulting - dictionary. If the *fieldnames* parameter is omitted, the values in the - first row of the *csvfile* will be used as the fieldnames. If the row read - has more fields than the fieldnames sequence, the remaining data is added as - a sequence keyed by the value of *restkey*. If the row read has fewer + :mod:`OrderedDict `. If the *fieldnames* parameter + is omitted, the values in the first row of the *csvfile* will be used as the + fieldnames. If the row read has more fields than the fieldnames sequence, + the remaining data is added as a sequence keyed by the value of *restkey*. + However the fieldnames are determined they retain their ordering in the + :mod:`OrderedDict `. If the row read has fewer fields than the fieldnames sequence, the remaining keys take the value of the optional *restval* parameter. Any other optional or keyword arguments are passed to the underlying :class:`reader` instance. + .. versionchanged:: 3.6 + Returned rows are now of type :class:`OrderedDict` rather than a + simple dictionary. + A short usage example:: >>> import csv diff -r b04560c3ce69 Lib/csv.py --- a/Lib/csv.py Wed Aug 03 22:02:42 2016 -0700 +++ b/Lib/csv.py Sat Aug 27 01:26:22 2016 +0800 @@ -11,6 +11,7 @@ __doc__ from _csv import Dialect as _Dialect +from collections import OrderedDict from io import StringIO __all__ = ["QUOTE_MINIMAL", "QUOTE_ALL", "QUOTE_NONNUMERIC", "QUOTE_NONE", @@ -116,7 +117,7 @@ # values while row == []: row = next(self.reader) - d = dict(zip(self.fieldnames, row)) + d = OrderedDict(zip(self.fieldnames, row)) lf = len(self.fieldnames) lr = len(row) if lf < lr: diff -r b04560c3ce69 Lib/test/test_csv.py --- a/Lib/test/test_csv.py Wed Aug 03 22:02:42 2016 -0700 +++ b/Lib/test/test_csv.py Sat Aug 27 01:26:22 2016 +0800 @@ -10,6 +10,7 @@ import gc import pickle from test import support +from itertools import permutations class Test_Csv(unittest.TestCase): """ @@ -1092,6 +1093,20 @@ fileobj.seek(0) self.assertEqual(fileobj.read(), expected) +class KeyOrderingTest(unittest.TestCase): + def test_ordering(self): + resultset = set() + for keys in permutations("abcde"): + with TemporaryFile('w+', newline='', encoding="utf-8") as fileobject: + dw = csv.DictWriter(fileobject, keys) + dw.writeheader() + fileobject.seek(0) + dr = csv.DictReader(fileobject) + kt = tuple(dr.fieldnames) + self.assertEqual(keys, kt) + resultset.add(kt) + # Final sanity check: were all permutations unique? + self.assertEqual(len(resultset), 120, "Key ordering: some key permutations not collected (expected 120)") class MiscTestCase(unittest.TestCase): def test__all__(self):