csv module
Monty’s csv module is a Rust port of CPython’s _csv parser and writer plus the DictReader and
DictWriter wrappers.
Field splitting, quoting, escaping, the QUOTE_* modes and the error messages match CPython 3.14 apart
from the notes below.
reader, writer, DictReader, DictWriter, Error, the six QUOTE_* constants, get_dialect,
list_dialects, field_size_limit (read-only, see below) and the three built-in dialects excel,
excel_tab and unix_dialect.
register_dialect,unregister_dialectandSnifferare missing from the module namespace. Module attributes cannot hold state between imports (see modules.md), so there is no dialect registry; pass format parameters or a dialect object instead.csv.field_size_limit(new_limit)raisesNotImplementedError: field_size_limit(): changing the limit is not supported. The limit is fixed at CPython’s default, 131072 characters, andfield_size_limit()reports it.__version__is missing.
- The built-in dialects are
_csv.Dialectobjects, not classes.csv.excel.delimiteranddialect=csv.excelwork, butcsv.excel()and subclassing it do not.csv.Dialectis_csv.Dialect, the resolved-dialect type, rather than CPython’s Python base class: it takes a dialect and the format parameters (csv.Dialect(delimiter=';')), andcsv.Dialect()is theexceldialect where CPython raises for its unsetdelimiter. reader(f, 'excel', dialect='unix')numbers the clashing position differently. The message isargument for function given by name ('dialect') and position (2); CPython forwards the keyword toDialect()and reports position 1.reader.dialectandwriter.dialectare fresh objects. Each access builds a new_csv.Dialectholding the resolved parameters, sor.dialect is r.dialectisFalse, where CPython returns the object stored at construction.- A file is loaded when the reader is built.
csv.reader(f)andcsv.DictReader(f)over anopen()file nobody has read yet read the whole file at construction so that any consumer (list(reader),next(reader), aforloop) works; CPython reads lazily on the first__next__. See open.md for the file buffer this relies on. - The file is loaded before the arguments are checked. When the reader’s file is loaded at construction, a host read error is reported before a bad dialect, format parameter or keyword would be; CPython validates the arguments first and never reads there.
writer.writerows()on a file issues one write. The rows are formatted and written to the file in a single host call, where CPython callswrite()once per row, so a row that fails to format leaves the file untouched instead of partly written.DictWriter.writerows()on a file flattens every dict before writing for the same reason. Any other target (an object with awrite()method) is called once per row as the rows arrive, but synchronously: awrite()that reaches an external function or host call raisesNotImplementedError(see classes.md for this restriction).writerow()has no such limit, since it returns whatever the singlewrite()call returns.writerow()reads the whole row before formatting any field. CPython formats each field as the row yields it, so with a row iterator that has side effects or raises part-way, the order of a field’sstr()call and the iterator’s own error can differ.DictWriterrows must bedicts.rowdict.keys()androwdict.get()are only resolved for real dicts; another mapping type raises the sameAttributeErrorCPython raises for a non-mapping.extrasaction='raise'reports unknown keys in dict order. CPython builds the message from a set difference, so its order varies.DictReader.reader,DictReader.line_numandDictWriter.writerare read-only. Assigning them raisesAttributeErrorwhere CPython, whoseDictReaderandDictWriterare plain Python classes, allows it.fieldnames,restkey,restvalanddialecton aDictReaderandfieldnames,restvalandextrasactionon aDictWritercan be assigned.copy.copy()andcopy.deepcopy()of aDictReaderorDictWriterraiseTypeError. The message iscannot pickle 'csv.DictReader' object; CPython copies the wrapper, sharing the underlying_csv.readeror_csv.writeron a shallow copy.repr(csv.Error('x'))is_csv.Error('x'), where CPython givesError('x'), as for the other dotted exception classes (see exceptions.md).- A dialect object’s attributes cannot come from properties.
dialect=SomeClassreads plain attributes (delimiter = ';'); an attribute implemented as apropertyraisesNotImplementedError.