Kursus Python / Membaca dan menulis CSV dengan DictReader dan DictWriter
CSV menyimpan baris dan bidang sebagai teks. Gunakan modul csv untuk menangani pemisah serta tanda kutip, lalu validasi dan konversi nilai angka karena DictReader biasanya mengembalikan isi bidang sebagai string.
Baca aturan CSV, bukan sekadar memisahkan koma
Bidang yang diapit tanda kutip dapat mengandung koma maupun newline. split(",") tidak menafsirkan aturan itu, sehingga dapat memecah satu nama menjadi beberapa bagian. DictReader menghubungkan isi bidang dengan nama pada baris header, sedangkan DictWriter menulis dictionary menurut urutan fieldnames.
Buka berkas CSV dengan newline="" agar modul csv menangani pemisah barisnya. Tentukan encoding juga. Pembacaan utf-8-sig menerima data UTF-8 dengan atau tanpa byte-order mark (BOM) di awal, sehingga BOM tidak menjadi bagian nama kolom pertama. Ini tidak berarti ia mendeteksi semua encoding dari spreadsheet.
CSV dari aplikasi berbeda dapat memakai pemisah atau aturan kutip yang berbeda. Sesuaikan dialek dengan format sumber, bukan mengganti semua tanda baca tanpa memahami datanya. Rujukan parameter dan perilakunya tersedia pada dokumentasi modul csv Python.
Tulis nama berkoma dan hitung jumlah
Gunakan folder latihan yang boleh diisi data percobaan. Program mengganti expenses-demo.csv dengan mode w pada setiap eksekusi. Simpan kode lengkap sebagai csv_demo.py dengan encoding UTF-8 dan jalankan python csv_demo.py dalam lingkungan proyek Python 3.12 atau lebih baru. Tidak diperlukan paket pihak ketiga.
import csv
from pathlib import Path
path = Path("expenses-demo.csv")
with path.open("w", encoding="utf-8", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["name", "amount"])
writer.writeheader()
writer.writerows([{ "name": "lunch, team", "amount": 8000}, {"name": "bus", "amount": 2500}])
total = 0
with path.open(encoding="utf-8-sig", newline="") as f:
reader = csv.DictReader(f)
if reader.fieldnames != ["name", "amount"]:
raise ValueError("unexpected header")
for row in reader:
total += int(row["amount"])
print(row["name"])
print("total:", total)
Keluaran yang diharapkan:
lunch, team
bus
total: 10500
Nama lunch, team tetap satu bidang, bukan dua kolom. Penulis CSV menambahkan tanda kutip yang dibutuhkan pada berkas. Ketika dibaca kembali, tanda kutip sintaks tidak menjadi bagian nama; koma di dalam nama tetap dipertahankan.
DictWriter mengubah nilai integer menjadi representasi teks. Pada pembacaan, int(row["amount"]) mengonversi string angka untuk penjumlahan. Hasil 10500 berasal dari 8000 + 2500, bukan dari penggabungan teks. Urutan header diperiksa tepat sebagai ["name", "amount"], sehingga nama, tambahan kolom, atau urutan header yang berbeda ditolak pada contoh ini.
Untuk memeriksa hasil, buka berkas sebagai teks dan lihat tanda kutip pada nama berkoma. Baca ulang dengan csv.reader, lalu periksa bahwa setiap record contoh terdiri dari dua bidang dan nama pertamanya tepat lunch, team. Koma yang terlihat pada isi bidang bukan bukti ada kolom tambahan.
Tentukan aturan angka dan bentuk record
int menolak string kosong, angka seperti 8,000, atau teks seperti 8000 KRW. Namun konversi itu sendiri tidak menetapkan aturan bisnis: angka negatif masih dapat dikonversi. Jika pengeluaran harus tidak negatif, tambahkan pemeriksaan rentang secara terpisah. Jangan menghapus semua karakter yang bukan digit karena itu dapat mengubah data tidak sah menjadi nilai lain yang tampak benar.
Header yang sesuai belum membuktikan semua baris sesuai. Pada perilaku bawaan DictReader, bidang tambahan pada suatu record disimpan di bawah kunci None, sedangkan bidang yang kurang mendapat nilai None. Contoh penjumlahan belum menolak semua bentuk record tambahan. Untuk impor nyata, periksa jumlah bidang, nama wajib, nilai kosong, serta jenis dan rentang angka sebelum menjumlahkan.
Nama header berulang juga harus ditangani secara sengaja karena dictionary tidak menyimpan dua nilai terpisah di bawah kunci yang sama. Pemeriksaan header contoh menolak pengulangan karena daftar harus sama persis dengan dua nama yang ditentukan.
enumerate(reader, start=2) dapat memberi label urutan record setelah header. Jika sebuah bidang berisi newline, label ini berbeda dari nomor baris fisik berkas. Atribut reader.line_num menunjukkan jumlah baris sumber yang telah dibaca, sehingga dapat menunjuk baris terakhir dari record multibaris. Sebutkan jenis nomor dalam laporan kesalahan agar pembaca menemukan data yang dimaksud.
Periksa pengulangan eksekusi dan ekspor spreadsheet
- Jalankan kode asli dan pastikan ada dua record data serta jumlah 10500. Jalankan lagi; jumlah record tidak bertambah karena mode
wmengganti berkas. - Untuk menguji header salah, ubah
fieldnamespenulis menjadi["name", "cost"]dan ganti kunciamountpada kedua record yang ditulis menjadicost. Biarkan pemeriksaan pembaca tetap asli. Program berhenti denganunexpected header. - Jangan hanya mengedit CSV lalu menjalankan seluruh skrip untuk uji header: bagian penulis akan menimpa perubahan itu sebelum pembaca berjalan. Pisahkan tahap baca atau ubah pembuat data seperti pada langkah sebelumnya.
- Pulihkan seluruh perubahan dan cocokkan kembali tiga baris keluaran asli.
Jika hanya mengganti fieldnames tanpa mengganti kunci record, DictWriter dapat gagal lebih awal karena masih menerima kunci yang tidak dikenal. Itu pengujian penulis yang berbeda dari pengujian header pembaca. Mengetahui tahap kegagalan membantu menentukan bagian yang harus diperbaiki.
CSV sendiri tidak menentukan tipe data atau kebijakan rumus spreadsheet. Program spreadsheet dapat menafsirkan nilai luar yang diawali karakter seperti = sebagai rumus. Pengapit tanda kutip CSV tidak otomatis memaksa sel menjadi teks pada semua aplikasi. Untuk ekspor yang dibagikan, tetapkan format dan penanganan teks sesuai aplikasi penerima serta asal datanya; jangan mengklaim bahwa kutip CSV menyelesaikan semua risiko interpretasi sel.
Penulisan dan pembacaan tetap mengikuti aturan mode, encoding, dan penutupan berkas. Pilihan format CSV melengkapi aturan tersebut dengan pemisah, pengutipan, dan pemeriksaan struktur record.




