What a CSV File Is, and Why the csv Module
Quick answer A CSV file is a plain text file where each line is one record and commas separate the fields, and you import the csv module rather than joining strings yourself because the module handles the quoting rules that silently corrupt hand-built lines.
A CSV file (Comma Separated Values) is an ordinary text file that stores a table. Each line is one record, and inside a line the fields are separated by commas.
Roll,Name,Marks
1,Aarav Sharma,88
2,Diya Nair,92
That is the entire format. Open the file in Notepad and you see text; open the very same file in Excel or Google Sheets and you see a spreadsheet. This is why almost every system hands you data as CSV — your school's marksheet export, a bank statement download, IRCTC booking history, a UPI transaction report. CSV is the plain-text handshake between two programs that share nothing else.
Where CSV sits among the file types in this unit:
| Feature | Text file (.txt) | CSV file (.csv) | Binary file (.dat) |
|---|---|---|---|
| Readable by a human | Yes | Yes | No |
| Structure | None — free text | Rows, comma-separated fields | Whatever pickle stored |
| Opens in | Notepad | Notepad and Excel | Neither |
| Module needed | None | csv | pickle |
| Type you get on reading back | str | str, always | Original type preserved |
| Mode strings | 'r', 'w', 'a' | 'r', 'w', 'a' | 'rb', 'wb', 'ab' |
Now the question that actually matters. If a CSV is nothing but commas and newlines, why import csv at all? Why not build each line yourself with ",".join(...)?
Because of one address. Watch what happens when a field itself contains a comma.
import csv
rows = [["Aarav Sharma", "Mumbai, Maharashtra", 45000],
["Diya Nair", "Kochi", 38000]]
# Way 1: joining strings by hand
f = open("hand.csv", "w")
for r in rows:
f.write(",".join(str(x) for x in r) + "\n")
f.close()
# Way 2: the csv module
f = open("safe.csv", "w", newline="")
csv.writer(f).writerows(rows)
f.close()
print("hand.csv:", repr(open("hand.csv").read()))
print("safe.csv:", repr(open("safe.csv").read()))
print("\nReading hand.csv back:")
for rec in csv.reader(open("hand.csv")):
print(len(rec), "fields ->", rec)
print("\nReading safe.csv back:")
for rec in csv.reader(open("safe.csv", newline="")):
print(len(rec), "fields ->", rec)
Real output:
hand.csv: 'Aarav Sharma,Mumbai, Maharashtra,45000\nDiya Nair,Kochi,38000\n'
safe.csv: 'Aarav Sharma,"Mumbai, Maharashtra",45000\nDiya Nair,Kochi,38000\n'
Reading hand.csv back:
4 fields -> ['Aarav Sharma', 'Mumbai', ' Maharashtra', '45000']
3 fields -> ['Diya Nair', 'Kochi', '38000']
Reading safe.csv back:
3 fields -> ['Aarav Sharma', 'Mumbai, Maharashtra', '45000']
3 fields -> ['Diya Nair', 'Kochi', '38000']
Look carefully at what broke. In hand.csv the address Mumbai, Maharashtra went in raw, so the comma inside the address became a separator. A record written with 3 fields came back with 4. Aarav's salary is now in field 3, where the state name should be. Every column after the damage is shifted by one — and Python raised no error at any point. That is the worst kind of bug: silent, and only discovered weeks later when someone's salary looks wrong.
The csv module saw the comma and wrapped the field in double quotes by itself: "Mumbai, Maharashtra". On the way back, reader() understood those quotes and returned 3 fields. You wrote no quoting logic at all. That is the whole reason the module exists — it already knows the escaping rules, so you never have to.
Every CSV program has the same three-step shape. First import csv. Then open the file with open(), choosing the mode: 'r' to read, 'w' to create or overwrite, 'a' to add to the end. Then close it with f.close(), or let a with block close it for you. Until the file is closed, what you wrote may still be sitting in a buffer and the file on disk can be empty.
One detail in the code above is not decoration: the newline="" in the open() call. Leave it out on Windows and every record picks up an extra carriage return, so a blank line appears between rows and csv.reader() hands you twice as many rows as you wrote. Section 3 proves it byte by byte — start typing newline="" now so it becomes a reflex.
One matching caution, so the reflex does not become superstition: newline="" belongs on the file object you are about to hand to csv.writer() or csv.reader(). When you only want to dump a file to the screen with print(open("data.csv").read()), plain open() is the right call — Section 3 shows why.
- A CSV file is a plain text file: one line per record, commas between fields. Notepad and Excel both open it, which is why it is the standard export format everywhere.
- Building CSV lines by hand with ",".join() breaks the moment a field contains a comma — a 3-field record came back as 4 fields with no error raised.
- csv.writer() automatically wraps any field containing a comma in double quotes, and csv.reader() understands those quotes on the way back. That automatic quoting is the reason to use the module.
- Reading any CSV file always returns strings, never numbers — unlike a binary/pickle file, which preserves the original type.
- Pass newline="" to open() whenever the file object is going to a csv.writer() or csv.reader(), and always close the file (or use a with block) before reading it back.
