csv
import csv 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:
| Parameter | Type | Default | Description |
|---|---|---|---|
csvfile | iterable | — | File-like object or list of strings to read |
dialect | str/Dialect | 'excel' | CSV dialect to use |
delimiter | str | ',' | Single character to separate fields |
quotechar | str | '"' | Character for quoting fields |
doublequote | bool | True | How to handle quotechar in fields |
escapechar | str | None | Escape character for certain modes |
lineterminator | str | '\r\n' | String for terminating lines (writer only) |
quoting | str | QUOTE_MINIMAL | When to quote fields |
skipinitialspace | bool | False | Ignore space after delimiter |
strict | bool | False | Raise 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:
| Parameter | Type | Default | Description |
|---|---|---|---|
f | file-like | — | File object to read |
fieldnames | sequence | first row | List of field names |
restkey | str | None | Key for extra fields in a row |
restval | str | None | Value for missing fields |
dialect | str/Dialect | 'excel' | CSV dialect to use |
*args | — | — | Passed to underlying reader |
**kwds | — | — | Passed 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:
| Parameter | Type | Default | Description |
|---|---|---|---|
csvfile | file-like | — | File object with write() method |
dialect | str/Dialect | 'excel' | CSV dialect to use |
delimiter | str | ',' | Single character to separate fields |
quotechar | str | '"' | Character for quoting fields |
doublequote | bool | True | How to handle quotechar in fields |
escapechar | str | None | Escape character |
lineterminator | str | '\r\n' | String for terminating lines |
quoting | str | QUOTE_MINIMAL | When to quote fields |
skipinitialspace | bool | False | Ignore space after delimiter |
strict | bool | False | Raise 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:
| Parameter | Type | Default | Description |
|---|---|---|---|
f | file-like | — | File object to write to |
fieldnames | sequence | — | Sequence of keys for column order |
restval | str | '' | Value for missing keys |
extrasaction | 'raise'/'ignore' | 'raise' | Action for extra dict keys |
dialect | str/Dialect | 'excel' | CSV dialect to use |
*args | — | — | Passed to underlying writer |
**kwds | — | — | Passed to underlying writer |
Note: The fieldnames parameter is required, unlike DictReader where it’s optional.
Methods:
writeheader()— Writes the field names as the header rowwriterow(row)— Writes a single row from a dictwriterows(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
| Constant | Description |
|---|---|
csv.QUOTE_ALL | Quote all fields |
csv.QUOTE_MINIMAL | Quote only special characters (default) |
csv.QUOTE_NONNUMERIC | Quote non-numeric fields; convert unquoted to float |
csv.QUOTE_NONE | Never quote; escape with escapechar |
csv.QUOTE_NOTNULL | Quote all fields except None |
csv.QUOTE_STRINGS | Quote all string fields |
Note:
QUOTE_NOTNULLandQUOTE_STRINGSwere added in Python 3.12.