Reading and Writing JSON, CSV and Parquet in Python
Which file format to use where, how to read each one without surprises, and why Parquet is the default for analytics.
PythonBeginner2 min readUpdated 11 Oct 2026
Three formats, three jobs
| Format | Shape | Schema | Best for |
|---|---|---|---|
| CSV | Rows of text | None — everything is a string | Exchange with spreadsheets and legacy systems |
| JSON / JSONL | Nested documents | Implicit, per record | APIs, logs, raw landing zones |
| Parquet | Columnar, compressed | Embedded and typed | Analytics, data lakes, warehouses |
CSV: always state the types
import csv
from decimal import Decimal
with open("orders.csv", newline="", encoding="utf-8") as f:
for row in csv.DictReader(f):
amount = Decimal(row["amount"]) # never float for money
qty = int(row["qty"])CSV has no types, no standard for nulls and many quoting dialects. Always parse explicitly and decide what an empty string means.
JSON Lines: one record per line
import json
with open("events.jsonl") as f:
for line in f: # streams: memory stays flat
event = json.loads(line)JSONL appends and streams well, so it suits raw landing zones. A single large JSON array must be loaded whole.
Parquet: columns, compression, types
import pyarrow.parquet as pq
table = pq.read_table("sales.parquet", columns=["store_id", "net_sales"]) # reads 2 columns onlyParquet stores each column together. A query that needs 2 of 40 columns reads about 5% of the bytes, and min/max statistics let engines skip whole row groups.
Common mistakes
- Using
floatfor money. UseDecimalor integer cents. - Opening CSVs without
newline="", which mangles embedded line breaks. - Writing thousands of tiny Parquet files. Aim for roughly 128 MB–1 GB per file.
Finished this note?
