csv

import csv
Added in v3.0 · Updated March 13, 2026 · Modules
csv files parsing data stdlib

The csv module is Python’s standard library for reading and writing CSV (Comma Separated Values) files. It provides classes for working with tabular data in CSV format, handling the details of parsing and generating CSV so you don’t have to worry about quoting rules, delimiters, or edge cases.

The module works with both sequence-based and dictionary-based data. The reader and writer classes handle rows as lists, while DictReader and DictWriter map rows to dictionaries using column headers.

Reading CSV Files

csv.reader()

This function creates a reader object that processes lines from a CSV file or any iterable of strings.

import csv

with open('data.csv', newline='') as csvfile:
    reader = csv.reader(csvfile)
    for row in reader:
        print(row)

Parameters:

ParameterTypeDefaultDescription
csvfileiterableFile-like object or list of strings to read
dialectstr/Dialect'excel'CSV dialect to use
delimiterstr','Single character to separate fields
quotecharstr'"'Character for quoting fields
doublequoteboolTrueHow to handle quotechar in fields
escapecharstrNoneEscape character for certain modes
lineterminatorstr'\r\n'String for terminating lines (writer only)
quotingstrQUOTE_MINIMALWhen to quote fields
skipinitialspaceboolFalseIgnore space after delimiter
strictboolFalseRaise Error on bad CSV

Returns: An iterator yielding lists of strings for each row.

Important: Always open files with newline='' when using csv module to prevent double newlines on Windows.

csv.DictReader()

This class works like csv.reader() but maps each row to a dictionary using field names from the header row.

import csv

with open('names.csv', newline='') as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        print(row['first_name'], row['last_name'])

Parameters:

ParameterTypeDefaultDescription
ffile-likeFile object to read
fieldnamessequencefirst rowList of field names
restkeystrNoneKey for extra fields in a row
restvalstrNoneValue for missing fields
dialectstr/Dialect'excel'CSV dialect to use
*argsPassed to underlying reader
**kwdsPassed to underlying reader

Returns: An iterator yielding dictionaries for each row.

Note: If fieldnames is omitted, the first row of the file is used as column headers. If provided explicitly, the first row is included in results.

Writing CSV Files

csv.writer()

This function creates a writer object that converts sequences of strings or numbers into delimited strings.

import csv

with open('output.csv', 'w', newline='') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(['Name', 'Age', 'City'])
    writer.writerow(['Alice', '30', 'London'])
    writer.writerow(['Bob', '25', 'Paris'])

Parameters:

ParameterTypeDefaultDescription
csvfilefile-likeFile object with write() method
dialectstr/Dialect'excel'CSV dialect to use
delimiterstr','Single character to separate fields
quotecharstr'"'Character for quoting fields
doublequoteboolTrueHow to handle quotechar in fields
escapecharstrNoneEscape character
lineterminatorstr'\r\n'String for terminating lines
quotingstrQUOTE_MINIMALWhen to quote fields
skipinitialspaceboolFalseIgnore space after delimiter
strictboolFalseRaise Error on bad CSV

Returns: A writer object with writerow() and writerows() methods.

csv.DictWriter()

This class works like csv.writer() but maps dictionaries to output rows.

import csv

with open('names.csv', 'w', newline='') as csvfile:
    fieldnames = ['first_name', 'last_name']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    
    writer.writeheader()
    writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})
    writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'})

Parameters:

ParameterTypeDefaultDescription
ffile-likeFile object to write to
fieldnamessequenceSequence of keys for column order
restvalstr''Value for missing keys
extrasaction'raise'/'ignore''raise'Action for extra dict keys
dialectstr/Dialect'excel'CSV dialect to use
*argsPassed to underlying writer
**kwdsPassed to underlying writer

Note: The fieldnames parameter is required, unlike DictReader where it’s optional.

Methods:

  • writeheader() — Writes the field names as the header row
  • writerow(row) — Writes a single row from a dict
  • writerows(rows) — Writes multiple rows from an iterable of dicts

Dialects

CSV dialects are predefined sets of formatting parameters for common file formats.

csv.excel

The default Excel dialect with comma delimiter and double quotes.

writer = csv.writer(csvfile, dialect='excel')  # default

csv.excel_tab

Tab-separated values like Excel’s “Text to Columns” export.

writer = csv.writer(csvfile, dialect='excel_tab')

csv.unix_dialect

UNIX-style CSV with all fields quoted and \n line endings.

writer = csv.writer(csvfile, dialect='unix')

Custom Dialects

Register your own dialect for reuse:

csv.register_dialect('mydialect', delimiter=';', quoting=csv.QUOTE_ALL)

# Use it later
reader = csv.reader(csvfile, dialect='mydialect')

# Unregister when done
csv.unregister_dialect('mydialect')

Reading Different Formats

Tab-separated files

with open('data.tsv', newline='') as f:
    reader = csv.reader(f, delimiter='\t')
    for row in reader:
        print(row)

Pipe-delimited files

with open('data.txt', newline='') as f:
    reader = csv.reader(f, delimiter='|', quotechar='-')
    for row in reader:
        print(row)

Handling missing values

# Default missing values become None in DictReader
with open('data.csv', newline='') as f:
    reader = csv.DictReader(f, restval='N/A')
    for row in reader:
        print(row.get('city', 'Unknown'))

Detecting CSV format automatically

with open('unknown.csv', newline='') as f:
    sample = f.read(1024)
    f.seek(0)
    
    dialect = csv.Sniffer().sniff(sample)
    reader = csv.reader(f, dialect)
    
    headers = next(reader)
    print(f"Detected headers: {headers}")

Common Patterns

Reading strings without a file

# Parse a CSV string
data = "name,age\nAlice,30\nBob,25"
for row in csv.reader(data.splitlines()):
    print(row)

# Or from a list
for row in csv.reader(['one,two,three', 'four,five,six']):
    print(row)

Writing to strings

import io

output = io.StringIO()
writer = csv.writer(output)
writer.writerow(['Name', 'Value'])
writer.writerow(['Test', '123'])

csv_string = output.getvalue()
print(csv_string)

Handling None and empty values

# None becomes empty string when writing
writer = csv.writer(csvfile, quoting=csv.QUOTE_NOTNULL)

# Reading with QUOTE_STRINGS treats empty as None
reader = csv.reader(csvfile, quoting=csv.QUOTE_STRINGS)

Error handling

import csv
import sys

try:
    with open('data.csv', newline='') as f:
        reader = csv.reader(f)
        for row in reader:
            print(row)
except csv.Error as e:
    sys.exit(f"CSV error: {e}")

Constants

ConstantDescription
csv.QUOTE_ALLQuote all fields
csv.QUOTE_MINIMALQuote only special characters (default)
csv.QUOTE_NONNUMERICQuote non-numeric fields; convert unquoted to float
csv.QUOTE_NONENever quote; escape with escapechar
csv.QUOTE_NOTNULLQuote all fields except None
csv.QUOTE_STRINGSQuote all string fields

Note: QUOTE_NOTNULL and QUOTE_STRINGS were added in Python 3.12.

See Also