csv

reader and writer turn lines into lists of strings and back; DictReader and DictWriter do the same with dicts keyed by the header. Open every CSV file with newline='' — and never parse CSV with str.split(',').

Data formatsPython 2.3+Live demo
Import
import csv
from csv import DictReader, DictWriter
Workhorses
reader, writer, DictReader, DictWriter
Formats
Dialects bundle the settings: excel (the default), excel-tab, unix — or pass delimiter=, quotechar=, quoting= … directly
Values
Every field is read as a str; the writer calls str() on everything except None, which becomes an empty field
Engine
Parser and writer state machines in C (Modules/_csv.c); DictReader, DictWriter and Sniffer are Python (Lib/csv.py)

Demo

Live evaluation
Type CSV text — write \n where a new line starts — and pick the delimiter. Each row comes back as a list of strings.
Try:
Inputs
textstrCSV text, \n = line break
delimiterstrone character
Code
import csv, io
text = 'name,age\\nAda,36\\nBob,41'.replace('\\n', '\n')
list(csv.reader(io.StringIO(text, newline=''), delimiter=','))
Result
[['name', 'age'], ['Ada', '36'], ['Bob', '41']]

The rows end in "\r\n": that is the excel dialect's line terminator on every platform, which is why files must be opened with newline='' (otherwise Windows turns it into "\r\r\n" and you get blank rows). A field containing the delimiter, the quote character or a line break is wrapped in quotes, and a quote inside is doubled. In "split vs csv", split cannot tell a quoted comma from a separator and keeps the quote characters; csv.reader removes them. A delimiter must be exactly one character — "||" raises TypeError.

Members

Common patterns

Read a CSV file into dicts
The header row becomes the keys. newline='' keeps quoted line breaks intact; say the encoding.
import csv
with open('people.csv', newline='', encoding='utf-8') as f:
    rows = list(csv.DictReader(f))
Write a CSV file
newline='' stops Windows from turning the writer's \r\n into \r\r\n (blank rows in Excel).
import csv
with open('out.csv', 'w', newline='', encoding='utf-8') as f:
    w = csv.writer(f)
    w.writerow(['name', 'age'])
    w.writerows(rows)
Tab- or semicolon-separated files
Same reader, different delimiter (excel-tab is the registered tab dialect).
import csv
with open('data.tsv', newline='', encoding='utf-8') as f:
    for row in csv.reader(f, delimiter='\t'):
        print(row)
CSV for Excel with non-ASCII text
utf-8-sig writes a BOM, which Excel uses to detect UTF-8.
import csv
with open('excel.csv', 'w', newline='', encoding='utf-8-sig') as f:
    csv.writer(f).writerows(rows)

Examples

1. Parse lines into lists
import csv list(csv.reader(['name,age', 'Ada,36']))
Returns
[['name', 'age'], ['Ada', '36']]
2. Quoted commas stay in the field
import csv next(csv.reader(['"Smith, John",42']))
Returns
['Smith, John', '42']
3. Rows as dicts
import csv, io f = io.StringIO('name,age\nAda,36\n', newline='') list(csv.DictReader(f))
Returns
[{'name': 'Ada', 'age': '36'}]
4. Writing quotes what needs it
import csv, io buf = io.StringIO(newline='') csv.writer(buf).writerow(['a,b', 'say "hi"', 3]) buf.getvalue()
Returns
'"a,b","say ""hi""",3\r\n'
5. Everything read is a str
import csv row = next(csv.reader(['1,2.5,True'])) [type(v).__name__ for v in row]
Returns
['str', 'str', 'str']
6. Round trip through a real file
import csv with open('t.csv', 'w', newline='') as f: csv.writer(f).writerows([['id', 'note'], [1, 'two\nlines']]) with open('t.csv', newline='') as f: rows = list(csv.reader(f)) rows
Returns
[['id', 'note'], ['1', 'two\nlines']]
7. The registered dialects
import csv sorted(csv.list_dialects())
Returns
['excel', 'excel-tab', 'unix']

Pitfalls

1. Splitting lines on commas
A comma inside a quoted field is data, not a separator. split breaks the field in two and keeps the quote characters.
line.split(',')
line = '"Smith, John",42'
line.split(',')
['"Smith', ' John"', '42']
csv.reader
import csv
line = '"Smith, John",42'
next(csv.reader([line]))
['Smith, John', '42']
2. Blank rows on Windows: forgetting newline=''
The writer ends rows with \r\n itself. A text file opened without newline='' on Windows translates the \n again, so each row ends in \r\r\n and readers see an empty row after every line. Here newline='\r\n' reproduces the Windows translation on any OS.
translated newlines
import csv
with open('t.csv', 'w', newline='\r\n') as f:
    csv.writer(f).writerows([['a', 'b'], ['c', 'd']])
with open('t.csv', newline='') as f:
    rows = list(csv.reader(f))
rows
[['a', 'b'], [], ['c', 'd'], []]
newline=''
import csv
with open('t.csv', 'w', newline='') as f:
    csv.writer(f).writerows([['a', 'b'], ['c', 'd']])
with open('t.csv', newline='') as f:
    rows = list(csv.reader(f))
rows
[['a', 'b'], ['c', 'd']]
3. Expecting numbers back
CSV has no types: the reader returns strings, so "36" + 1 fails. Convert the columns you need.
use as is
import csv
name, age = next(csv.reader(['Ada,36']))
age + 1
TypeError: can only concatenate str (not "int") to str
int(...)
import csv
name, age = next(csv.reader(['Ada,36']))
int(age) + 1
37

When to use

Use it
  • Spreadsheet exports and imports (Excel, Google Sheets, LibreOffice)
  • Simple tabular data exchange between programs and databases
  • Streaming large tables row by row without loading them whole
Reach for something else
  • Nested or typed data → json
  • Heavy analysis, joins, type inference → pandas.read_csv
  • Reading .xlsx workbooks → a library such as openpyxl (csv cannot read them)

Notes

CPython impl
Modules/_csv.c implements reader, writer, Dialect, Error and the registry; Lib/csv.py adds DictReader, DictWriter, Sniffer and the excel / excel_tab / unix_dialect classes
Line endings
Readers accept \n, \r\n and \r; the excel dialect writes \r\n (unix writes \n). Open files with newline='' for both
Encoding
csv works on str only — open files in text mode with an explicit encoding; utf-8-sig for files meant for Excel

FAQ

with open('file.csv', newline='', encoding='utf-8') as f: rows = list(csv.reader(f)) gives a list of lists of strings; csv.DictReader(f) gives one dict per row keyed by the header line.