Tutorials Logic, IN info@tutorialslogic.com

Python CSV Files: Read and Write Spreadsheet Data

CSV Files

CSV files store table-like data as plain text rows and columns.

Python has a csv module so you do not need to split lines manually.

Use CSV when exchanging simple spreadsheet data, exports, reports, logs, or bulk records.

Read Rows

A CSV reader parses records according to quoting and delimiter rules; it does more than split a line at each comma. A quoted field may contain a comma, a quote, or even a newline. Use csv.reader for positional rows and csv.DictReader when a header should name each field.

Open real files as text with an explicit encoding and newline="". The empty newline setting lets the csv module recognize embedded newlines and write platform-safe row endings itself. UTF-8 is a practical default when the producer and consumer agree on it; utf-8-sig can also consume a UTF-8 byte-order mark exported by some spreadsheet tools.

  • Use DictReader when columns have stable names and csv.reader when position is the contract.
  • Treat every field as text until application code validates and converts it.
  • Inspect reader.fieldnames before processing an import whose columns are required.
  • Use reader.line_num in error messages; a logical record can span more than one physical line.

Read CSV Text

Read CSV Text
import csv
from io import StringIO

data = StringIO("name,score\nMaya,90\nRavi,82\n")

for row in csv.DictReader(data):
    print(row["name"], int(row["score"]))
Output
Maya 90
Ravi 82

DictReader uses the first row as field names.

Write Rows

csv.writer writes sequences, while csv.DictWriter maps named values into a declared column order. DictWriter requires fieldnames because dictionaries may contain fields that do not belong in the export. Its default extrasaction="raise" is useful: an unexpected key fails visibly instead of silently dropping data.

Write the header once for a new file, then pass rows to writerow or writerows. None is serialized as an empty field by the standard writer, so choose an explicit missing-value convention when an empty string and a missing value must remain distinct after a round trip.

  • Keep fieldnames in one schema constant shared by validation and export code.
  • Use quoting=csv.QUOTE_ALL or another deliberate policy when a receiving system has strict import rules.
  • Write to a temporary file and replace the destination only after success when a partial report would be harmful.
  • Do not build CSV by joining strings; the writer handles delimiters, quotes, and embedded line breaks.

Write CSV Text

Write CSV Text
import csv
from io import StringIO

output = StringIO()
writer = csv.DictWriter(output, fieldnames=["name", "passed"])
writer.writeheader()
writer.writerow({"name": "Maya", "passed": True})

print(output.getvalue())
Output
name,passed
Maya,True

DictWriter writes the header and then a row matching those fields.

Dialects, Delimiters, and Quoting

CSV is a family of tabular text formats, not one perfectly uniform format. A supplier may send semicolon-separated records, single-quoted fields, or a tab-separated export. Pass a known dialect or explicit formatting parameters when the data contract is documented. csv.Sniffer can suggest a delimiter from a representative sample, but detection is a heuristic and should not replace validation.

Quoting controls how delimiters and line breaks remain part of one field. QUOTE_MINIMAL quotes only fields that require it. QUOTE_ALL is predictable for strict downstream systems. QUOTE_NONNUMERIC also converts unquoted input fields to floats, which is rarely a complete business-data conversion strategy. Parse first, then apply field-specific types.

  • Set delimiter to one character such as comma, semicolon, or tab.
  • Keep quotechar and escape behavior identical on both sides of an exchange.
  • Use strict=True when malformed quoting must stop an import instead of being tolerated.
  • Save the chosen dialect with the integration contract so future exports remain compatible.

Parse a Semicolon-Separated Export

Parse a Semicolon-Separated Export
import csv
from io import StringIO

source = StringIO('product;price\n"Tea, green";4.50\n')
reader = csv.DictReader(source, delimiter=";")

row = next(reader)
print(row["product"])
print(float(row["price"]) * 2)
Output
Tea, green
9.0

The comma belongs to the quoted product name; only semicolons separate columns. Price conversion happens after parsing.

Validate an Import Contract

Parsing proves that a row follows CSV syntax; it does not prove that the row is valid for the application. Validate the header, required fields, type conversions, ranges, and cross-field rules before mutating a database. Collect row-numbered errors when users should be able to correct a batch, or stop at the first error when partial acceptance is unsafe.

DictReader can expose irregular rows. Extra values are stored under restkey, and missing values use restval. Set explicit sentinels when these cases must be distinguished from a genuinely empty field. Normalize only what the contract permits: trimming an identifier may be safe, while changing capitalization in a case-sensitive code may corrupt it.

  • Reject duplicate or missing header names before reading business rows.
  • Convert each field in a small validation function that reports the row and column.
  • Stage valid records, then commit them together when all-or-nothing import behavior is required.
  • Limit accepted file size and field size for uploads from untrusted users.

Report Invalid Rows with Their Record Number

Report Invalid Rows with Their Record Number
import csv
from io import StringIO

source = StringIO("name,score\nMaya,91\nRavi,high\n")
reader = csv.DictReader(source)

for row in reader:
    try:
        score = int(row["score"])
        if not 0 <= score <= 100:
            raise ValueError("score must be 0..100")
        print(f"accepted: {row['name']}")
    except (TypeError, ValueError) as error:
        print(f"record {reader.line_num}: {error}")
Output
accepted: Maya
record 3: invalid literal for int() with base 10: 'high'

The parser supplies text fields and the application applies the integer and range contract. line_num identifies the failing source record.

CSV Limits and Security

CSV is appropriate for flat records and interchange, but it has no native types, nested objects, constraints, relationships, or transaction model. Use JSON for nested exchange data and a database when records need durable querying, concurrent updates, or enforced integrity. Large files should be streamed row by row rather than loaded into one list.

A syntactically valid export can still be dangerous. Spreadsheet programs may interpret cells beginning with =, +, -, or @ as formulas. If untrusted text will be opened in a spreadsheet, apply the receiving organization's formula-injection policy and preserve the original value separately. Never assume quoting alone disables formula execution.

  • Set upload, record, and field limits before parsing untrusted input.
  • Keep import validation separate from database writes so rejected rows leave no partial state.
  • Record the encoding, delimiter, header schema, date format, and null convention in the exchange contract.
  • Test commas, quotes, Unicode, blank fields, embedded newlines, malformed rows, and the largest supported file.
Before you move on

Can You Use CSV Files?

5 checks
  • You can read CSV rows without manual split calls.
  • You can use DictReader when headers are available.
  • You can convert number columns before calculations.
  • You can write headers and rows with DictWriter.
  • You can explain when CSV is simpler than JSON or a database.

CSV Row Traps

  • Splitting by comma manually

    Use the csv module because quoted commas and newlines can break manual splitting.
  • Forgetting numeric conversion

    CSV values are text. Convert scores, prices, and counts before math.
  • Mismatched field names

    Keep DictWriter fieldnames aligned with the dictionaries you write.

Try this next

Import and Export Rows

0 of 3 completed

  1. Read name and score rows, convert scores to int, and print the class average.
  2. Write only rows where passed is true into a new CSV output.
  3. Detect rows where email or score is empty and print the row number.

Questions About CSV Files

No. CSV is plain text table data. Excel files can contain formulas, sheets, styles, and richer workbook features.

Use CSV for flat rows and columns. Use JSON for nested objects, lists, and structured API-style data.

It lets the csv module handle row endings consistently, especially across operating systems.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.