Home / Blog / Other text utilities

CSV records

Comma-Separated Fields: Quoting and Delimiters

Read comma-separated fields with quotes and embedded commas, run a Python CSV round trip, and verify types, encoding and destination requirements.

Comma-Separated Fields: Quoting and Delimiters

Comma-separated fields need an agreed quoting rule. In a common CSV representation, a comma separates fields, a double quote encloses a field containing special characters, and two consecutive double quotes represent one quote inside a quoted field. Splitting every line on a comma is therefore insufficient for general CSV.

Read a record with punctuation

The following record has three fields, even though four commas are visible. Its second field contains a comma, and its third contains literal quotation marks.

00123,"ACME, Inc.","She said ""yes"""

The parsed values are the identifier 00123, the name ACME, Inc., and the note She said "yes". Keep the identifier as text when its leading zero matters. A spreadsheet may interpret an untyped import as a number and remove the zero; correct CSV syntax alone does not control the spreadsheet’s data types.

Use a parser instead of string splitting

This Python example reads the record, checks its fields and writes it back using the standard library. The writer handles quoting, so the application does not need a hand-built chain of replacements.

import csv
import io

source = '00123,"ACME, Inc.","She said ""yes"""\r\n'
rows = list(csv.reader(io.StringIO(source, newline="")))
assert rows == [["00123", "ACME, Inc.", 'She said "yes"']]
out = io.StringIO(newline="")
csv.writer(out, lineterminator="\r\n").writerows(rows)
assert list(csv.reader(io.StringIO(out.getvalue(), newline=""))) == rows
print(out.getvalue(), end="")

The second assertion checks meaning after serialization rather than assuming a particular visual quoting style proves success. For an actual file, open it with an explicit encoding and newline="" as the Python documentation describes. Agree on the encoding with the receiving application; a correct delimiter cannot repair text already decoded using the wrong character set.

A row is not always one physical line

A quoted field may contain a line break. The next visible line can therefore be a continuation of the same record. Count rows with the CSV parser, not by counting newline characters. Keep the entire quoted field intact when copying a small example into a test file.

Similarly, the text "a,b" can be one field while a,b is two fields. An empty field between two commas differs from a missing column at the end of a malformed row. Decide whether your table permits empty values and verify the number of columns for every parsed record. A header row can name columns but does not enforce their types or required values by itself.

Match the destination dialect

Some systems call a semicolon-separated file CSV. Others use a tab, a different quote convention or a required header. Ask for the destination’s delimiter, encoding, line endings and column order. Do not change an extension and assume the content changed with it. A TSV file renamed to .csv still contains tabs.

Spaces after delimiters also need care. Under the common RFC format they can be part of the next field. A friendly display list such as apple, banana may therefore carry a leading space in the second value when parsed literally. Use a writer for structured records and reserve Comma Separator for the simpler task of joining plain lines.

A small acceptance fixture

Before sending a large dataset, include a leading-zero identifier, an accented name, an empty value, an embedded comma, a quotation mark and a multiline note in a disposable sample. Export, import into the real destination, then compare those exact values. Check that no extra column appeared and that no row was merged or split. Keep the original file until the destination has passed this round trip.

If a receiving application treats cell text beginning with an equals sign as a formula, define an import policy for that application. CSV quoting does not by itself force every spreadsheet to treat a value as inert text. Use explicit column types or an agreed data-cleaning rule without silently changing meaningful source data.

References

Python CSV reader and writer; RFC 4180 format description.