Berkas teks adalah salah satu sumber data yang paling sering dibaca oleh program, mulai dari catatan sederhana hingga data hasil ekspor aplikasi lain. Topik ini membahas fungsi open() beserta mode bacanya, disiplin penulisan encoding="utf-8", dan cara mengiterasi berkas per baris. Setelah membacanya, berkas teks dapat dibaca dan ditulis secara andal tanpa bergantung pada pengaturan platform tempat program dijalankan.
Membaca berkas dengan open dan with#
Fungsi open() menerima jalur berkas dan mode sebagai argumen utamanya, lalu mengembalikan file object, yaitu objek perantara yang menyediakan seluruh operasi baca dan tulis. Mode "r" (baca) dipakai untuk membaca dan merupakan mode bawaan apabila argumen mode ditinggalkan. Karena berkas terbuka adalah sumber daya sistem operasi yang jumlahnya terbatas, pemanggilan open() selalu dibungkus pernyataan with agar berkas ditutup secara otomatis setelah bloknya selesai.
from pathlib import Path
Path("surat.txt").write_text("Halo\nDunia\n", encoding="utf-8")
with open("surat.txt", encoding="utf-8") as f:
isi = f.read()
print(isi, end="")Halo
DuniaMetode read() mengembalikan seluruh isi berkas sebagai satu string. Baris pertama pada contoh membuat berkas contoh terlebih dahulu, sehingga program dapat dijalankan berulang kali tanpa menyiapkan berkas secara manual. Argumen encoding="utf-8" diberikan secara eksplisit, dan alasan pentingnya dijelaskan pada bagian tersendiri. Setelah blok with berakhir, berkas sudah tertutup, dan pemanggilan read() lagi pada objek yang sama ditolak dengan error ValueError.
Menulis berkas dengan mode w dan a#
Mode pada open() menentukan perilaku tulisnya. Mode "w" (tulis) membuka berkas untuk ditulis dan mengosongkannya begitu dibuka, sedangkan mode "a" (tambah) menyisipkan teks baru di akhir berkas tanpa menyentuh isinya. Kedua mode tersebut membuat berkas baru secara otomatis apabila berkas yang dimaksud belum ada, sehingga penyiapan berkas kosong tidak diperlukan.
with open("log-tes.txt", "w", encoding="utf-8") as f:
f.write("baris pertama\n")
f.write("baris kedua\n")
with open("log-tes.txt", "a", encoding="utf-8") as f:
f.write("baris ketiga\n")
with open("log-tes.txt", encoding="utf-8") as f:
print(f.read(), end="")baris pertama
baris kedua
baris ketigaMetode write() tidak menambahkan tanda baris baru secara otomatis, sehingga karakter \n ditempatkan secara manual di akhir setiap baris. Apabila mode "a" pada pembukaan kedua diganti menjadi "w", isi berkas akan menyusut menjadi satu baris karena mode tersebut mengosongkan berkas sejak awal. Perilaku ini sering luput dari perhatian ketika program menulis ke berkas yang sama berulang kali dalam satu proses yang panjang.
Iterasi per baris#
Objek berkas teks dapat diiterasi seperti sekuens, dan setiap putaran menghasilkan satu baris lengkap dengan tanda \n di ujungnya. Pola ini lebih hemat memori daripada read() karena seluruh isi tidak perlu dimuat sekaligus, sehingga cocok untuk berkas berukuran besar. Metode rstrip() dipakai untuk membuang tanda baris baru beserta spasi di ujung baris sebelum baris tersebut dicetak.
with open("sekolah.txt", "w", encoding="utf-8") as f:
f.write("SD Amanatul Ummah\nSD Negeri 01\nSMP Negeri 3\n")
with open("sekolah.txt", encoding="utf-8") as f:
for nomor, baris in enumerate(f, start=1):
print(nomor, baris.rstrip())1 SD Amanatul Ummah
2 SD Negeri 01
3 SMP Negeri 3Fungsi enumerate() menyediakan nomor baris yang dimulai dari 1 melalui argumen start. Metode readlines() juga tersedia dan mengembalikan seluruh baris sebagai list, tetapi perulangan langsung atas objek berkas tetap lebih disukai untuk berkas besar karena tidak menumpuk semuanya di memori. Satu perbedaan yang penting diperhatikan adalah iterator berkas hanya dapat digunakan satu kali, sehingga perulangan kedua pada objek berkas yang sama tidak lagi menghasilkan baris apa pun.
Disiplin encoding utf-8#
Encoding adalah aturan pemetaan antara karakter dan rangkaian byte, dan satu berkas teks pada dasarnya hanyalah byte yang menunggu ditafsirkan. Apabila argumen encoding ditinggalkan, Python memakai encoding bawaan platform, dan nilainya berbeda antar sistem operasi, sehingga program yang berjalan baik di satu mesin dapat rusak di mesin lainnya. Karena itu, setiap pemanggilan open() untuk berkas teks pada jalur ini selalu menyertakan encoding="utf-8" sebagai kebiasaan baku.
teks = "kopi à 25 ribu\n"
with open("menu.txt", "wb") as f:
f.write(teks.encode("utf-8"))
try:
with open("menu.txt", encoding="ascii") as f:
f.read()
except UnicodeDecodeError as e:
print(type(e).__name__)
with open("menu.txt", encoding="utf-8") as f:
print(f.read(), end="")UnicodeDecodeError
kopi à 25 ribuMode "wb" menulis byte mentah tanpa penafsiran apa pun, dan byte yang sama kemudian dibaca dengan dua encoding yang berbeda. Encoding ascii menolak karakter à karena bukan anggotanya, sehingga error UnicodeDecodeError muncul, sedangkan utf-8 membaca byte yang sama dengan benar. Error semacam ini selalu berarti byte berkas dan encoding yang diberikan tidak sepakat, bukan berarti berkasnya rusak.
Kesalahan umum#
Kesalahan pertama adalah membuka berkas yang isinya masih dibutuhkan dengan mode "w". Isi lama hilang pada saat open() dijalankan, jauh sebelum satu karakter pun ditulis, dan tidak ada mekanisme pemulihan pada level open(). Perbaikannya adalah menulis ke berkas sementara terlebih dahulu, lalu menggantikan berkas aslinya setelah penulisan selesai, atau memakai mode "a" bila isi lama memang ingin dipertahankan.
Kesalahan kedua adalah mengiterasi objek berkas yang sama dua kali tanpa membukanya ulang. Iterator berkas habis setelah putaran pertama, sehingga hasilnya tampak kosong tanpa pesan error apa pun.
with open("sekolah.txt", encoding="utf-8") as f:
print(len(list(f)))
print(len(list(f)))3
0Perbaikannya adalah membuka berkas kembali pada perulangan berikutnya, atau memanggil f.seek(0) untuk mengembalikan posisi baca ke awal berkas. Kesalahan ketiga adalah meninggalkan argumen encoding dengan alasan programnya sudah berjalan baik. Pada platform dengan encoding bawaan yang berbeda, teks sama dapat menghasilkan karakter rusak atau error UnicodeDecodeError, sehingga argumen tersebut tetap ditulis eksplisit di semua tempat.
Ringkasan#
open()di dalam blokwithmembuka dan menutup berkas secara deterministik, sedangkan mode"r","w", dan"a"menentukan perilaku baca, tulis, dan tambah.- Metode
read()memuat seluruh isi sekaligus, sedangkan iterasi langsung atas objek berkas memproses satu baris per putaran dan lebih hemat memori. - Argumen
encoding="utf-8"ditulis eksplisit agar perilaku program sama pada semua platform. UnicodeDecodeErrormenandakan byte berkas tidak cocok dengan encoding yang diberikan saat membaca.
Referensi#
- Reading and Writing Files — Python Software Foundation
— Bagian tutorial resmi tentang
open(), mode berkas, dan pernyataanwith. - open — Built-in Functions — Python Software Foundation
— Dokumentasi lengkap fungsi
open()beserta mode dan argumenencoding-nya. - Unicode HOWTO — Python Software Foundation — Penjelasan resmi tentang Unicode, encoding, dan penanganan error dekode.