csv is a module in Python's standard library; csv.writer and csv.reader are callables within that module that return writer and reader objects respectively for encoding and decoding CSV rows. Calling writerow on a writer object wraps a field containing a comma, a quotation mark, or a newline in quotation marks, and escapes a literal quotation mark inside such a field by doubling it. Iterating over a reader object reverses these transformations. Testing four string values through this write-then-read sequence showed the original values recovered unchanged.
The round-trip mechanism
Round-tripping means encoding a value with csv.writer and then decoding the result with csv.reader to get back the original value. csv.writer, a callable in the csv module, returns a writer object; calling writerow on that object examines each field before writing it: if the field contains a comma, a quotation mark, or a newline, writerow wraps the entire field in quotation marks, first doubling any literal quotation mark already inside it. csv.reader, the counterpart callable, returns a reader object; iterating over that object reverses this by stripping the surrounding quotation marks and converting any doubled quotation marks back into a single quotation mark.
Testing four values through this sequence — plain text, text containing a comma, text containing a quotation mark, and text containing a newline — showed each value recovered exactly as it was written, confirming the round trip for these specific cases.
Comma and newline handling
A field containing a comma is wrapped in quotation marks by csv.writer because an unquoted comma would otherwise be read as separating two fields. When csv.reader encounters that quoted field, it recognizes that the comma inside the quotation marks is part of the field's value rather than a delimiter.
A field containing a newline is handled the same way: csv.writer wraps it in quotation marks so the newline is understood as part of the field's content rather than the end of a row. In testing, a value containing a newline was correctly read back as a single field by csv.reader, rather than being split into two rows.
Quote escaping inside quoted fields
When a field's value itself contains a quotation mark, calling writerow on the writer object returned by csv.writer doubles that character and wraps the whole field in quotation marks. Iterating over the reader object returned by csv.reader detects a doubled quotation mark inside a quoted field and converts it back to a single quotation mark in the value it returns.
This doubling convention is the default escaping behavior for csv.writer and csv.reader in the csv module. In the tested case, a value containing a quotation mark was written, read back, and matched the original value exactly.
File handling and the newline setting
The csv module's documentation recommends opening files with the newline parameter set to an empty string when reading or writing CSV data, so that line-ending characters are passed through to csv.reader and csv.writer without being translated by the file layer first. This matters especially when a field's value legitimately contains a newline inside quotation marks.
The testing described here used an in-memory text buffer configured the same way, rather than an actual file on disk, so the effect of this setting on real files across different operating systems was not directly exercised. The recommendation to use this setting for files comes from the module's documentation rather than from the tests performed.
Verification through testing
To check that a round trip works, a value is passed to csv.writer, the resulting text is captured, and that text is then passed to csv.reader; the parsed result is compared to the original value. This sequence was run for the four values described earlier, and each one matched its original after being written and read back.
This kind of check is useful for confirming behavior on specific inputs. If a round trip fails for a particular value, the mismatch points to either how the file or buffer was opened or how that value interacts with the quoting and escaping behavior of csv.writer and csv.reader.
Practical considerations and limitations
These results come from running the csv module's reader and writer callables against a small set of synthetic string values in a single Python 3.12 environment, using the module's default dialect settings. Other libraries such as pandas, spreadsheet applications, and third-party CSV parsers were not tested.
Because only the default dialect was exercised, these findings should not be treated as evidence that csv.writer and csv.reader comply with any formal CSV specification, or that every CSV parser handles quoting and escaping the same way. Pairing output from csv.writer with a differently configured reader could still produce mismatched results.
Run the verified example
Python
import csv
import io
cases = ["plain", "comma, inside", 'a "quote"', "two\nlines"]
for value in cases:
buffer = io.StringIO(newline="")
csv.writer(buffer).writerow(["00123", value])
encoded = buffer.getvalue()
decoded = next(csv.reader(io.StringIO(encoded, newline="")))
assert decoded == ["00123", value]
print(repr(value), "round-trip:", decoded == ["00123", value])Observed output
'plain' round-trip: True
'comma, inside' round-trip: True
'a "quote"' round-trip: True
'two\nlines' round-trip: TrueTest scope and sources
Executed 2026-09-06 with Python 3.12.13 on Darwin. Tests use standard-library csv and synthetic strings. No Excel, pandas or third-party parser was executed. Do not generalize to every CSV dialect.