Học chuyển đổi hai chiều với json.dumps/loads và ensure_ascii, đọc/ghi theo vị trí với csv.writer/reader, và đọc/ghi theo tên cột với DictWriter/DictReader qua dữ liệu Titanic.
Bài này nói về I/O cho hai định dạng dữ liệu có cấu trúc thường gặp — json, hay được web API dùng, và csv, mở gọn gàng trong phần mềm bảng tính.
JSON vs CSV — Khi nào dùng cái nào?JSON có thể biểu diễn cặp khóa/giá trị và cấu trúc lồng nhau, nên xuất hiện khắp nơi trong response của web API và file cấu hình. CSV là định dạng bảng "1 dòng = 1 bản ghi" phẳng, mở trực tiếp trong bảng tính như Excel, là chủ lực cho phân tích dữ liệu.
json — Chuyển đổi hai chiều giữa object Python và chuỗi JSON
JSON (JavaScript Object Notation) là định dạng văn bản nhẹ biểu diễn cấu trúc chỉ bằng "cặp khóa/giá trị" và "list có thứ tự", được dùng làm tiêu chuẩn cho response web API và file cấu hình. Module json của Python chuyển đổi dict, list, chuỗi, số, bool và None sang và từ JSON.
Chỉ cần nhớ hai hàm cơ bản. json.dumps(object) chuyển Python → chuỗi JSON, và json.loads(string) chuyển chuỗi JSON → Python. Chữ s ở cuối là viết tắt của string — phân biệt với dump / load, vốn làm việc trực tiếp với file.
Tính đối xứng của json.dumps và json.loadsHàng trên: dumps (dump string) = chiều Python → chuỗi JSON. Hàng dưới: loads (load string) = chiều chuỗi JSON → Python. Các biến thể không có s (dump / load) làm việc trực tiếp với đối tượng file.
Hàm
Vai trò
Ghi chú
json.dumps(obj)
Python → chuỗi JSON
trả về str
json.loads(text)
chuỗi JSON → Python
trả về dict / list / v.v.
json.dump(obj, file)
Python → ghi vào file
truyền f từ open()
json.load(file)
file → Python
truyền f từ open()
indent=N
in đẹp với thụt lề N space
cho người đọc
ensure_ascii=False
xuất ký tự non-ASCII nguyên dạng
mặc định escape chúng
ensure_ascii mặc định là True
Mặc định, json.dumps({"name": "café"}) xuất '{"name": "caf\u00e9"}' — ký tự non-ASCII bị escape thành \u. Về kỹ thuật vẫn hợp lệ, nhưng khó đọc cho người và làm phình kích thước file, nên với dữ liệu chứa ký tự non-ASCII (dấu, emoji, CJK, v.v.), hãy tạo thói quen truyền ensure_ascii=False.
Chuyển thông tin user thành JSON, parse ngược lại thành object Python, và kiểm tra kiểu của từng biến bằng type().
① Hãy import module json.
② Hãy xây dict với name="Minh" và list mặt hàng ["Apple", "Banana"] (hai key: name và items).
③ Hãy chuyển dict thành chuỗi JSON in đẹp (có thụt lề) rồi in, sau đó in type(text): để hiện kiểu của chuỗi JSON (tắt escape non-ASCII phòng khi dữ liệu chứa dấu, emoji, v.v.).
④ Hãy parse chuỗi JSON ngược lại thành object Python, rồi in type(parsed): và type(items): lần lượt (lấy items ra từ parsed).
⑤ Từ object đã parse, hãy in tên: ◯◯ và Mặt hàng đầu tiên: ◯◯ (phần tử đầu của items).
(Nếu chạy đúng, phần giải thích sẽ hiện ra.)
Python Editor
Chạy code để xem đầu ra
Cơ bản về csv — Xử lý dòng với reader và writer
CSV (Comma-Separated Values) là định dạng văn bản thuần trong đó một dòng phân tách bằng dấu phẩy bằng một bản ghi, và vì phần mềm bảng tính như Excel mở được trực tiếp, nó xuất hiện khắp nơi trong workflow nghiệp vụ. Module csv của Python cung cấp các hàm để đọc và ghi định dạng này theo từng dòng.
Cơ bản gồm csv.writer(file) và csv.reader(file): cái trước ghi một list giá trị thành một dòng, cái sau đọc CSV từng dòng một thành một list giá trị. Hai điểm cần lưu ý: thứ nhất, mọi thứ đọc về đều là chuỗi — nếu cần số nguyên, hãy tự chuyển đổi bằng int(). Thứ hai, luôn truyền newline='' cho open(...) để module csv tự quản lý ký tự xuống dòng.
csv.writer và csv.reader làm gìwriter.writerow(list)ghi một list giá trị thành một dòng CSV. reader làm chiều ngược lại — lấy một dòng CSV ra thành một list giá trị — và quan trọng là mọi giá trị đều ra dạng chuỗi.
Luôn truyền newline='' cho open
Module csv tự quản lý ký tự xuống dòng, nên bạn cần truyền newline='' kiểu open("x.csv", "w", newline=''). Bỏ qua thì có thể dẫn đến CSV chứa dòng trống trên Windows — một lỗi điển hình được tài liệu Python chính thức nhắc đến.
Ghi một list user vào CSV, rồi đọc lại từng dòng dùng file output.csv trên hệ thống file ảo trong trình duyệt (VFS).
① Hãy import module csv.
② Hãy mở output.csv ở chế độ ghi (với newline=''), tạo writer, và ghi 3 dòng: header ["name", "age"] và hai dòng dữ liệu ["Minh", 30] và ["Linh", 25].
③ Hãy mở lại file đó ở chế độ đọc (với newline=''), tạo reader, và in từng dòng bằng for row in reader:.
Python Editor
Chạy code để xem đầu ra
DictWriter và DictReader — Đọc và ghi theo tên cột
csv.writer / reader ở phần trước hoạt động theo vị trí, nên thêm cột hoặc đổi thứ tự buộc bạn phải sửa lại mọi truy cập row[0] / row[1]. DictWriter / DictReader là phiên bản đọc và ghi theo tên cột (header) — bạn có thể ghi một list các dict thẳng vào CSV và đọc lại thành một list các dict.
Dữ liệu thực tế phần lớn là CSV có dòng header, nên trong dự án thực tế bạn sẽ dùng các hàm này nhiều hơn hẳn.
Vì sao DictWriter / DictReader tiện lợiDictWriter biến list các dict thành CSV với dòng header được định nghĩa bởi fieldnames. DictReader làm chiều ngược lại — đọc CSV có dòng header thành list các dict, để bạn truy cập giá trị theo tên cột kiểu row["name"].
Ghi một list-of-dicts user vào users.csv, rồi đọc lại và in từng dòng đã định dạng. Thử đọc theo tên cột thay vì theo vị trí.
① Hãy import csv.
② Hãy xây list hai user (3 cột: name / age / city).
- User đầu: name="Minh", age=30, city="Tokyo"
- User sau: name="Linh", age=25, city="Osaka"
③ Hãy mở users.csv ở chế độ ghi, tạo DictWriter, và ghi header + dữ liệu (truyền fieldnames=["name", "age", "city"]).
④ Hãy mở lại file và tạo DictReader, in từng dòng theo dạng {name} ({age} tuổi) {city}.
Python Editor
Chạy code để xem đầu ra
Ví dụ thực tế: Tổng hợp titanic.csv
Đến giờ ta đã tạo các tập dữ liệu nhỏ trong code và ghi chúng ra. Hãy kết thúc bằng việc đọc một tập dữ liệu thực và tổng hợp. Đối tượng là tập dữ liệu Titanic nổi tiếng trên Kaggle (891 dòng / 12 cột), với các cột như PassengerId / Survived (0 = chết, 1 = sống sót) / Pclass (hạng cabin) / Name / Sex / Age / Fare.
python_console của bài thực hành nạp sẵn CSV bên ngoài vào hệ thống file ảo (VFS) trong trình duyệt qua fileUrls, nên code của bạn chỉ cần gọi open("titanic.csv"). Ta sẽ viết cùng một bài tập với cả csv.reader (theo vị trí) và csv.DictReader (theo tên cột).
Dùng csv.reader theo vị trí để đọc titanic.csv và đếm tổng số hành khách và số người sống sót.
① Hãy import module csv.
② Hãy mở titanic.csv ở chế độ đọc (với newline='') và tạo reader.
③ Hãy bỏ qua dòng header bằng next(reader).
④ Hãy lặp phần còn lại với for row in reader: và đếm total và survived (các dòng có cột Survived = index 1 là "1").
⑤ Hãy in Tổng: 891 và Sống sót: 342.
Python Editor
Chạy code để xem đầu ra
Dùng csv.DictReader theo tên cột để đọc titanic.csv và tính trung bình của cột Age. Dữ liệu Titanic có dòng mà Age bị trống, nên ta cũng xử lý điều đó.
① Hãy import csv.
② Hãy mở titanic.csv ở chế độ đọc (với newline='') và tạo DictReader.
③ Trong vòng lặp, lấy row["Age"] của từng dòng và gom chỉ những dòng không rỗng dưới dạng float(row["Age"]) vào một list.
④ Hãy in số dòng hợp lệ và tuổi trung bình (2 chữ số thập phân) như sau:
- Bản ghi hợp lệ: ◯ (kỳ vọng: 714)
- Tuổi trung bình: ◯◯.◯◯ (kỳ vọng: 29.70)
Python Editor
Chạy code để xem đầu ra
QUIZ
Kiểm tra kiến thức
Hãy trả lời từng câu hỏi một.
Câu 1json.dumps({"name": "café"}, ensure_ascii=False) cho ra kết quả nào?
Câu 2Kiểu của giá trị trả về khi đọc dòng bằng csv.reader là gì?
Câu 3Cái nào hợp nhất để đọc một CSV có dòng header thành list các dict?