csv.Dialect

Seven class attributes describe a CSV format. Every reader and writer validates them into an internal _csv.Dialect — single keyword arguments like delimiter=";" override one setting on top of the dialect.

csv classPython 2.3+Live demo
Common call
class Pipes(csv.excel): delimiter = '|'
Returns
a dialect class to pass as dialect=Pipes
Replaces
repeating delimiter=…, quotechar=… on every call
Watch out
subclass csv.excel, not bare csv.Dialect, unless you set all seven attributes
class csv.Dialect
→ class

Demo

Live evaluation
Pass delimiter and quotechar (empty = None) and read back the validated dialect the reader uses.
Try:
Inputs
delimiterstrone character
quotecharstr | Noneempty = None
Code
import csv
d = csv.reader([], delimiter=',', quotechar='"').dialect
(d.delimiter, d.quotechar, d.escapechar, d.doublequote, d.skipinitialspace, d.quoting, d.lineterminator)
Result
(',', '"', None, True, False, 0, '\r\n')

The validation runs when the reader is created: a delimiter must be exactly one character (TypeError otherwise), and delimiter, quotechar and escapechar must differ ("bad delimiter or quotechar value", a ValueError). quotechar=None switches quoting to 3 (QUOTE_NONE) when quoting is not given. A space is a fine delimiter; a space as quotechar or escapechar is only rejected ("bad quotechar value") when skipinitialspace=True. In "subclass", skipinitialspace=True drops the spaces after each delimiter — but not the ones before it.

Parameters

NameTypeRequiredDescription
delimiterstr (1 char)no (',')Separates fields.
quotecharstr (1 char) | Noneno ('"')Wraps fields that contain special characters. None turns quoting off (QUOTE_NONE).
escapecharstr (1 char) | Noneno (None)Removes the special meaning of the next character (needed with QUOTE_NONE, or doublequote=False).
doublequoteboolno (True)A quotechar inside a field is written (and read) as two quotechars.
skipinitialspaceboolno (False)Ignore spaces right after a delimiter when reading.
lineterminatorstrno ('\r\n')Ends rows written by the writer. The reader ignores it: it always accepts \r, \n and \r\n.
quotingintno (QUOTE_MINIMAL)One of the six QUOTE_* constants.
strictboolno (False)Raise csv.Error on malformed input instead of guessing.

Return value

class — Subclass it and set the class attributes; pass the class (or a name registered for it) as dialect=.

Common patterns

A named format for your project
Subclass csv.excel and override what differs; register it if you want to refer to it by name.
import csv

class Pipes(csv.excel):
    delimiter = '|'

with open('data.psv', newline='', encoding='utf-8') as f:
    rows = list(csv.reader(f, dialect=Pipes))
Backslash-escaped format
No quoting at all, special characters escaped with a backslash.
import csv

class Escaped(csv.excel):
    quoting = csv.QUOTE_NONE
    escapechar = '\\'

w = csv.writer(f, dialect=Escaped)
Override one setting
Keyword arguments win over the dialect.
import csv
reader = csv.reader(f, dialect='excel-tab', skipinitialspace=True)

Examples

1. The defaults (excel)
import csv d = csv.get_dialect('excel') (d.delimiter, d.quotechar, d.escapechar, d.doublequote, d.skipinitialspace, d.lineterminator, d.quoting, d.strict)
Returns
(',', '"', None, True, False, '\r\n', 0, False)
2. Subclass excel, change one thing
import csv class Semi(csv.excel): delimiter = ';' next(csv.reader(['a;"b;c"'], dialect=Semi))
Returns
['a', 'b;c']
3. Keyword arguments override
import csv csv.reader([], dialect='excel-tab', delimiter='|').dialect.delimiter
Returns
'|'
4. doublequote=False escapes the quote
import csv, io buf = io.StringIO(newline='') csv.writer(buf, doublequote=False, escapechar='\\').writerow(['say "hi"']) buf.getvalue()
Returns
'say \\"hi\\"\r\n'
5. Registered dialects are _csv.Dialect
import csv d = csv.get_dialect('excel') (type(d).__name__, isinstance(d, csv.Dialect))
Returns
('Dialect', False)
6. Settings are read-only
import csv csv.get_dialect('excel').delimiter = ';'
Returns
AttributeError: attribute 'delimiter' of '_csv.Dialect' objects is not writable

Pitfalls

1. Subclassing bare csv.Dialect
csv.Dialect sets every attribute to None as a placeholder. Leave one unset and validation fails — here quoting is still None.
csv.Dialect
import csv
class Semi(csv.Dialect):
    delimiter = ';'
    quotechar = '"'
    lineterminator = '\r\n'
list(csv.reader(['a;b'], dialect=Semi))
TypeError: "quoting" must be an integer
csv.excel
import csv
class Semi(csv.excel):
    delimiter = ';'
list(csv.reader(['a;b'], dialect=Semi))
[['a', 'b']]
2. Changing lineterminator to change what the reader accepts
The reader ignores lineterminator — it always splits rows on \r, \n and \r\n. Only the writer uses it.
lineterminator=';'
import csv, io
list(csv.reader(io.StringIO('a;b;c', newline=''), lineterminator=';'))
[['a;b;c']]
split rows first
import csv
list(csv.reader('a;b;c'.split(';')))
[['a'], ['b'], ['c']]

When to use

Use it
  • A format you read or write in several places
  • Bundling several non-default settings under one name
Reach for something else
  • A single change → pass delimiter=… directly
  • Guessing the format of an unknown file → csv.Sniffer

Notes

CPython impl
Two classes share the name: Lib/csv.py's csv.Dialect (the base class you subclass, all attributes None) and _csv.Dialect in Modules/_csv.c (dialect_new validates the attributes; reader.dialect, writer.dialect and get_dialect() return it)
Validation
Wrong types raise TypeError ("delimiter" must be a 1-character string), conflicting characters ValueError (bad delimiter or quotechar value); instantiating a csv.Dialect subclass re-raises the TypeError as csv.Error
strict
A setting of _csv.Dialect too (default False), though Lib/csv.py does not list it on csv.Dialect

FAQ

Subclass csv.excel and override the attributes that differ (class Pipes(csv.excel): delimiter = '|'), then pass dialect=Pipes — or csv.register_dialect('pipes', Pipes) and pass dialect='pipes'.