Đọc CSV
Bạn sẽ học được
- Đọc CSV bằng
csv.DictReadermà không cần thư viện ngoài. - Vì sao mọi giá trị đọc từ CSV đều là chuỗi.
- Ghi CSV bằng
DictWriteran toàn với dấu phẩy trong dữ liệu. - Xử lý encoding, BOM và file lỗi.
- Khi nào nên chuyển sang pandas.
Khái niệm cốt lõi
CSV là văn bản thuần: mỗi dòng một bản ghi, các trường cách nhau bằng dấu phẩy. Module csv của thư viện chuẩn xử lý đúng các trường hợp khó như dấu phẩy trong nội dung, dấu nháy, xuống dòng — những thứ mà split(",") làm sai.
import csv
import io
raw = """ngay,mat_hang,so_luong,don_gia
2026-01-05,Áo thun,2,150000
2026-01-06,Quần jean,1,450000
2026-01-07,Áo thun,3,150000
"""
reader = csv.DictReader(io.StringIO(raw))
rows = list(reader)
print(rows[0]){'ngay': '2026-01-05', 'mat_hang': 'Áo thun', 'so_luong': '2', 'don_gia': '150000'}DictReader dùng dòng đầu làm tên cột và trả mỗi dòng thành dict. Trong file thật, thay io.StringIO(raw) bằng open("sales.csv", newline="", encoding="utf-8").
Hai tham số quan trọng khi open:
newline=""để modulecsvtự xử lý ký tự xuống dòng, tránh dòng trống trên Windows.encoding="utf-8"để đọc đúng tiếng Việt. File xuất từ Excel thường có BOM — dùngutf-8-sigđể bỏ BOM ở đầu.
Mọi giá trị đều là chuỗi
Đây là điểm quan trọng nhất khi mới làm việc với CSV. DictReader không suy luận kiểu; so_luong là '2', không phải 2.
for row in rows:
revenue = int(row["so_luong"]) * int(row["don_gia"])
print(row["ngay"], row["mat_hang"], revenue)2026-01-05 Áo thun 300000
2026-01-06 Quần jean 450000
2026-01-07 Áo thun 450000Nếu quên ép kiểu, row["so_luong"] * row["don_gia"] sẽ nhân chuỗi với chuỗi và báo TypeError: can't multiply sequence by non-int of type 'str'. Hoặc tệ hơn, "2" + "3" cho "23" — không lỗi nhưng sai hoàn toàn.
Tổng doanh thu:
total = sum(int(r["so_luong"]) * int(r["don_gia"]) for r in rows)
print(total)1200000Trong dữ liệu thật, cột số có thể chứa dấu phẩy hàng nghìn ("1,200,000"), khoảng trắng, hoặc ô trống. Hàm chuyển đổi cần xử lý:
def to_int(raw):
if not raw or not raw.strip():
return 0
return int(raw.replace(",", "").strip())Với số thực, dùng float và lưu ý dấu thập phân: CSV kiểu Việt có thể dùng , — khi đó phải biết quy ước của nguồn trước khi thay dấu.
Ghi CSV
out = io.StringIO()
writer = csv.DictWriter(out, fieldnames=["ngay", "mat_hang", "so_luong", "don_gia"])
writer.writeheader()
writer.writerows(rows)
print(out.getvalue().strip().splitlines()[0])ngay,mat_hang,so_luong,don_giaVới file thật:
with open("clean.csv", "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=["ngay", "mat_hang", "so_luong", "don_gia"])
writer.writeheader()
writer.writerows(rows)fieldnamesphải khớp khóa trong dict, nếu khôngDictWriterbáoValueError.extrasaction="ignore"bỏ qua khóa thừa nếu dict có cột ngoài danh sách.encoding="utf-8-sig"giúp Excel mở file có tiếng Việt không bị lỗi font.
Không tự nối chuỗi bằng ",".join(...): nếu trường chứa dấu phẩy, dấu nháy hoặc xuống dòng, file sẽ hỏng. csv tự bọc nháy và escape đúng chuẩn.
Đọc file lớn
reader là iterator, không nạp toàn bộ file vào bộ nhớ. Với file lớn, xử lý từng dòng:
with open("sales.csv", newline="", encoding="utf-8") as f:
for row in csv.DictReader(f):
xu_ly(row)Chỉ dùng list(reader) khi thực sự cần duyệt nhiều lần hoặc file nhỏ. Với hàng triệu dòng, pandas.read_csv nhanh hơn và có kiểu dữ liệu tự động, nhưng csv đủ và không cần cài thêm gì.
Thực hành
- Đọc đoạn CSV mẫu bằng
DictReader, in dòng đầu. - Ép
so_luongvàdon_giasangint, tính doanh thu từng dòng. - Tính tổng doanh thu bằng generator.
- Ghi lại dữ liệu ra CSV bằng
DictWriter, mở bằng Excel để kiểm tra tiếng Việt. - Thử
split(",")trên một trường có dấu phẩy để thấy vì sao cần modulecsv. - Đọc file với
utf-8-sigvà so sánh khi dùngutf-8.
Lỗi thường gặp
| Triệu chứng | Nguyên nhân | Cách sửa |
|---|---|---|
TypeError khi nhân | Quên ép kiểu chuỗi | int()/float() trước khi tính |
"23" thay vì 5 | Cộng chuỗi | Ép số trước khi cộng |
| Dòng trống giữa file | Thiếu newline="" | Thêm khi open |
| Tiếng Việt bị lỗi font | Sai encoding/BOM | utf-8-sig |
UnicodeDecodeError | File không phải UTF-8 | Thử latin-1 hoặc xác định nguồn |
KeyError cột | Tên cột lệch hoa thường/khoảng trắng | In reader.fieldnames |
| File ghi hỏng | Tự nối chuỗi bằng dấu phẩy | Dùng csv.writer |
ValueError khi ghi | Dict thừa khóa | extrasaction="ignore" |
Tóm tắt
csv.DictReadertrả dict theo tên cột;DictWriterghi an toàn.- Mọi giá trị CSV là chuỗi — luôn ép kiểu trước khi tính.
open(..., newline="", encoding="utf-8"); dùngutf-8-sigcho Excel.- Reader là iterator, phù hợp file lớn.
- Không tự tách/ghép CSV bằng chuỗi thô.
Use ← → to move between lessons