csv.QUOTE_MINIMAL

QUOTE_MINIMAL (the default) quotes only fields that need it. The others quote everything, everything but numbers, nothing, only str values, or everything but None — and three of them also change what the reader returns.

csv constantsPython 2.3+ (QUOTE_STRINGS, QUOTE_NOTNULL: 3.12+)Live demo
Common call
csv.writer(f, quoting=csv.QUOTE_ALL)
Returns
0 MINIMAL · 1 ALL · 2 NONNUMERIC · 3 NONE · 4 STRINGS · 5 NOTNULL
Replaces
adding quotes to values yourself
Watch out
on READING, NONNUMERIC turns every unquoted field into a float
csv.QUOTE_MINIMAL, csv.QUOTE_ALL, csv.QUOTE_NONNUMERIC, csv.QUOTE_NONE, csv.QUOTE_STRINGS, csv.QUOTE_NOTNULL
→ int

Demo

Live evaluation
The row ['Ada', 36, 2.5, None, ''] written with quoting 0 to 5.
Try:
Inputs
quotingint0 to 5
Code
import csv, io
buf = io.StringIO(newline='')
csv.writer(buf, quoting=0, escapechar='\\').writerow(['Ada', 36, 2.5, None, ''])
buf.getvalue()
Result
'Ada,36,2.5,,\r\n'

Writing: None and '' both become empty fields; QUOTE_STRINGS and QUOTE_NOTNULL quote '' but not None, so the difference survives the file. Reading: QUOTE_NONNUMERIC converts every unquoted, non-empty field with float() — "Ada" raises ValueError: could not convert string to float: 'Ada'. QUOTE_STRINGS converts too, and also turns an empty unquoted field into None; QUOTE_NOTNULL only does the None part. QUOTE_NONE treats quote characters as ordinary text.

Common patterns

Quote every field
Some importers insist on it.
import csv
with open('out.csv', 'w', newline='', encoding='utf-8') as f:
    csv.writer(f, quoting=csv.QUOTE_ALL).writerows(rows)
Keep None and empty string apart (3.12+)
Write and read with the same style.
import csv
with open('out.csv', 'w', newline='', encoding='utf-8') as f:
    csv.writer(f, quoting=csv.QUOTE_NOTNULL).writerows(rows)
with open('out.csv', newline='', encoding='utf-8') as f:
    rows = list(csv.reader(f, quoting=csv.QUOTE_NOTNULL))
Numbers back as floats
Write with QUOTE_NONNUMERIC so text is quoted, read with it so numbers come back as float.
import csv
with open('nums.csv', newline='', encoding='utf-8') as f:
    rows = list(csv.reader(f, quoting=csv.QUOTE_NONNUMERIC))

Examples

1. They are plain ints
import csv [csv.QUOTE_MINIMAL, csv.QUOTE_ALL, csv.QUOTE_NONNUMERIC, csv.QUOTE_NONE, csv.QUOTE_STRINGS, csv.QUOTE_NOTNULL]
Returns
[0, 1, 2, 3, 4, 5]
2. QUOTE_ALL
import csv, io buf = io.StringIO(newline='') csv.writer(buf, quoting=csv.QUOTE_ALL).writerow(['a', 1]) buf.getvalue()
Returns
'"a","1"\r\n'
3. QUOTE_NONNUMERIC round trip
import csv, io buf = io.StringIO(newline='') csv.writer(buf, quoting=csv.QUOTE_NONNUMERIC).writerow(['Ada', 36]) next(csv.reader([buf.getvalue()], quoting=csv.QUOTE_NONNUMERIC))
Returns
['Ada', 36.0]
4. QUOTE_NOTNULL keeps None
import csv, io buf = io.StringIO(newline='') csv.writer(buf, quoting=csv.QUOTE_NOTNULL).writerow(['a', None, '']) (buf.getvalue(), next(csv.reader([buf.getvalue()], quoting=csv.QUOTE_NOTNULL)))
Returns
('"a",,""\r\n', ['a', None, ''])
5. QUOTE_NONE needs an escapechar
import csv, io csv.writer(io.StringIO(), quoting=csv.QUOTE_NONE).writerow(['a,b'])
Returns
_csv.Error: need to escape, but no escapechar set
6. quotechar=None implies QUOTE_NONE
import csv csv.reader([], quotechar=None).dialect.quoting
Returns
3
7. Anything else is rejected
import csv csv.reader([], quoting=6)
Returns
TypeError: bad "quoting" value

Pitfalls

1. Reading with QUOTE_NONNUMERIC when text is unquoted
The reader cannot know which unquoted fields were meant as text. Any non-number that is not quoted stops the read.
QUOTE_NONNUMERIC
import csv
list(csv.reader(['name,age', 'Ada,36'], quoting=csv.QUOTE_NONNUMERIC))
ValueError: could not convert string to float: 'name'
convert yourself
import csv
rows = csv.reader(['name,age', 'Ada,36'])
header = next(rows)
[(name, int(age)) for name, age in rows]
[('Ada', 36)]
2. Expecting QUOTE_ALL to change what is read
For reading, QUOTE_ALL behaves like QUOTE_MINIMAL: quotes are removed and everything is a str.
QUOTE_ALL
import csv
next(csv.reader(['"1",2'], quoting=csv.QUOTE_ALL))
['1', '2']
QUOTE_NONNUMERIC
import csv
next(csv.reader(['"1",2'], quoting=csv.QUOTE_NONNUMERIC))
['1', 2.0]

When to use

Use it
  • QUOTE_ALL / QUOTE_NONNUMERIC: the consumer expects quoted text
  • QUOTE_NOTNULL / QUOTE_STRINGS: None must survive a round trip (3.12+)
  • QUOTE_NONE + escapechar: formats that use backslash escapes instead of quotes
Reach for something else
  • QUOTE_NONNUMERIC for reading files you did not write that way

Notes

CPython impl
Modules/_csv.c — enum QuoteStyle; csv_writerow picks the initial quoted flag per field, parse_save_field applies the float() / None rules when reading
Version
QUOTE_STRINGS and QUOTE_NOTNULL were added in Python 3.12
Numbers
For QUOTE_NONNUMERIC/STRINGS writing, "numeric" means int, float, bool, Decimal… (anything that supports the number protocol)

FAQ

Pass quoting=csv.QUOTE_ALL to csv.writer (or DictWriter). Every field, numbers included, is wrapped in quotes.