DictWriter.writeheader

One call, one row: the fieldnames, formatted with the same dialect as the data. Call it once, before the first writerow.

DictWriter methodPython 2.7+ (returns the write() result since 3.8)Live demo
Common call
w.writeheader()
Returns
the write() result, e.g. 10 for 'name,age\r\n'
Replaces
w.writer.writerow(fieldnames)
Watch out
not automatic — and calling it twice writes the header twice
DictWriter.writeheader()
→ int | None

Demo

Live evaluation
Comma-separated field names → the header line and what writeheader returned.
Try:
Inputs
fieldnameslist[str]column names
Code
import csv, io
buf = io.StringIO(newline='')
n = csv.DictWriter(buf, fieldnames=['name', 'age']).writeheader()
(n, buf.getvalue())
Result
(10, 'name,age\r\n')

With fieldnames=[] the header is a row with no fields, which is written as a bare "\r\n" (2 characters). writeheader builds dict(zip(fieldnames, fieldnames)) and passes it to writerow, so it follows every dialect rule — under QUOTE_NONE a name containing a comma has nothing to protect it and csv.Error is raised.

Common patterns

Header, then rows
The usual three lines.
import csv
with open('out.csv', 'w', newline='', encoding='utf-8') as f:
    w = csv.DictWriter(f, fieldnames=['name', 'age'])
    w.writeheader()
    w.writerows(rows)
Append without repeating the header
Only write it when the file is new or empty.
import csv, os
new = not os.path.exists('log.csv') or os.path.getsize('log.csv') == 0
with open('log.csv', 'a', newline='', encoding='utf-8') as f:
    w = csv.DictWriter(f, fieldnames=['time', 'event'])
    if new:
        w.writeheader()
    w.writerow(entry)
Human-friendly header labels
writeheader always writes the keys; for other labels write the row yourself.
w = csv.DictWriter(f, fieldnames=['name', 'age'])
w.writer.writerow(['Full name', 'Age (years)'])
w.writerows(rows)

Examples

1. Writes the field names
import csv, io buf = io.StringIO(newline='') csv.DictWriter(buf, ['name', 'age']).writeheader() buf.getvalue()
Returns
'name,age\r\n'
2. Returns the write() result
import csv, io csv.DictWriter(io.StringIO(), ['name', 'age']).writeheader()
Returns
10
3. Uses the dialect
import csv, io buf = io.StringIO(newline='') csv.DictWriter(buf, ['a', 'b'], dialect='excel-tab').writeheader() buf.getvalue()
Returns
'a\tb\r\n'
4. Same as writing the keys as a row
import csv, io a, b = io.StringIO(newline=''), io.StringIO(newline='') csv.DictWriter(a, ['x', 'y']).writeheader() csv.writer(b).writerow(['x', 'y']) a.getvalue() == b.getvalue()
Returns
True
5. Read it back as fieldnames
import csv, io buf = io.StringIO(newline='') w = csv.DictWriter(buf, ['name', 'age']) w.writeheader() w.writerow({'name': 'Ada', 'age': 36}) buf.seek(0) csv.DictReader(buf).fieldnames
Returns
['name', 'age']

Pitfalls

1. Calling writeheader inside the loop
Every call writes another header row.
per row
import csv, io
buf = io.StringIO(newline='')
w = csv.DictWriter(buf, ['n'])
for n in (1, 2):
    w.writeheader()
    w.writerow({'n': n})
buf.getvalue()
'n\r\n1\r\nn\r\n2\r\n'
once
import csv, io
buf = io.StringIO(newline='')
w = csv.DictWriter(buf, ['n'])
w.writeheader()
for n in (1, 2):
    w.writerow({'n': n})
buf.getvalue()
'n\r\n1\r\n2\r\n'
2. A generator as fieldnames
DictWriter turns an iterator into a list, so this works — but the generator is used up by the time you try to reuse it elsewhere.
reuse the generator
import csv, io
names = (c for c in ['a', 'b'])
csv.DictWriter(io.StringIO(), names).writeheader()
list(names)
[]
use a list
import csv, io
names = ['a', 'b']
csv.DictWriter(io.StringIO(), names).writeheader()
list(names)
['a', 'b']

When to use

Use it
  • Once, right after creating a DictWriter for a new file
Reach for something else
  • Appending to a file that already has a header
  • Custom header labels → w.writer.writerow([...])

Notes

CPython impl
Lib/csv.py — header = dict(zip(self.fieldnames, self.fieldnames)); return self.writerow(header)
Return value
Returns the writerow result since Python 3.8; None before

FAQ

Call writer.writeheader() once after creating the DictWriter and before writing rows. It writes the fieldnames as the first row.