pathlib dalam praktik

Membaca, menulis, glob, dan penelusuran rekursif melalui pathlib dalam praktik.

Daftar isi

Modul pathlib menghadirkan kelas Path yang mewakili jalur berkas dan direktori sebagai objek, lengkap dengan metode untuk membaca, menulis, mencari, dan menelusurinya. Topik ini membahas pembuatan objek Path beserta atributnya, pembacaan dan penulisan berkas, pencarian berkas dengan pola glob, serta penelusuran rekursif pada pohon direktori. Setelah topik ini dibaca, pekerjaan berkas sehari-hari dapat dilakukan tanpa menyusun jalur berupa string secara manual.

Objek Path dan atributnya#

Pemanggilan Path("...") membuat objek jalur, dan operator / menyambungkan beberapa bagian jalur menjadi satu. Jalur relatif dibuat tanpa awalan pemisah, sehingga seluruh jalurnya ditafsirkan terhadap direktori kerja saat program dijalankan. Objek hasilnya menyediakan atribut yang memecah satu jalur menjadi bagian-bagiannya tanpa operasi string apa pun.

python proyek-path.py
from pathlib import Path

p = Path("proyek-laporan")
p.mkdir(exist_ok=True)
(p / "laporan.txt").write_text("Pendapatan: 120\n", encoding="utf-8")
f = p / "laporan.txt"
print(f.exists())
print(f.name, f.stem, f.suffix)
print(f)
print(f.parent)
text Keluaran
True
laporan.txt laporan .txt
proyek-laporan/laporan.txt
proyek-laporan

Atribut name berisi nama berkas lengkap, stem berisi nama tanpa akhirannya, suffix berisi akhiran beserta titiknya, dan parent berisi direktori tempat berkas itu berada. Metode mkdir() membuat direktorinya, dan argumen exist_ok=True membuat pemanggilan ulang tidak menimbulkan error ketika direktori sudah ada. Apabila direktori induknya belum ada, argumen parents=True ditambahkan agar seluruh rantai direktori dibuat sekaligus.

Objek Path juga dapat memuat jalur absolut, dan metode Path.home() menyediakan direktori rumah pengguna tanpa menebak sistem operasinya. Pencetakan objek jalur menampilkan pemisah yang sesuai dengan sistem operasi tempat program dijalankan, sehingga kode yang sama menghasilkan garis miring pada sistem berbasis Unix dan pemisah milik Windows tanpa penyesuaian apa pun. Sifat inilah yang menjadikan Path lebih aman daripada penyusunan string jalur secara manual.

Membaca dan menulis dengan read_text dan write_text#

Kelas Path menyediakan pintasan read_text() dan write_text() yang membungkus open() ke dalam satu pemanggilan. Metode write_text() menimpa seluruh isi berkas dengan teks yang diberikan dan mengembalikan jumlah karakter yang ditulis, sedangkan read_text() mengembalikan seluruh isi sebagai string. Keduanya menerima argumen encoding, dan argumen tersebut tetap ditulis eksplisit meskipun pemanggilannya singkat.

python Contoh: read_text, write_text, dan unlink
from pathlib import Path

f = Path("catatan.txt")
f.write_text("kopi\nroti\n", encoding="utf-8")
print(f.read_text(encoding="utf-8"), end="")
teks = f.read_text(encoding="utf-8")
f.write_text(teks + "gula\n", encoding="utf-8")
print(len(f.read_text(encoding="utf-8").splitlines()))
f.unlink()
print(f.exists())
text Keluaran
kopi
roti
3
False

Menambahkan satu baris dilakukan dengan membaca isi lama, menyambungkannya, lalu menulis kembali secara utuh, karena write_text() tidak menyediakan mode tambah. Metode unlink() menghapus berkasnya dari sistem berkas, dan pemanggilan exists() setelahnya mengembalikan False sebagai konfirmasi. Untuk berkas yang dibaca dan ditulis berkali-kali dalam satu alur kerja, pasangan metode ini menghilangkan kebutuhan penutupan berkas secara manual.

Pencarian berkas dengan glob#

Metode glob() mencari berkas yang namanya cocok dengan sebuah pola wildcard di dalam satu direktori. Tanda * mewakili sejumlah karakter apa pun, sehingga pola "*.csv" berarti seluruh nama berkas yang berakhiran .csv. Hasilnya berupa urutan objek Path, dan urutan aslinya tidak dijamin oleh modul ini, sehingga hasil tersebut diurutkan dengan sorted() sebelum digunakan.

python Contoh: glob dengan pola *.csv
from pathlib import Path

root = Path("data-cuaca")
root.mkdir(exist_ok=True)
(root / "januari.csv").write_text("tanggal,suhu\n", encoding="utf-8")
(root / "februari.csv").write_text("tanggal,suhu\n", encoding="utf-8")
(root / "catatan.md").write_text("# Catatan cuaca\n", encoding="utf-8")
for f in sorted(root.glob("*.csv")):
    print(f)
text Keluaran
data-cuaca/februari.csv
data-cuaca/januari.csv

Dua berkas CSV tercetak dalam urutan abjad, sedangkan catatan.md tidak ikut karena akhirannya tidak cocok dengan pola. Selain *, pola glob juga menerima tanda ? yang mencocokkan tepat satu karakter dan tanda kurung siku seperti [ab] yang mencocokkan salah satu karakter yang tercantum, sehingga penyaringan sederhana dapat dinyatakan tanpa kondisi tambahan. Pencarian glob() hanya memeriksa isi direktori itu sendiri dan tidak turun ke subdirektorinya, sehingga pola ini tepat untuk struktur data yang datar. Apabila kecocokan dihitung tanpa memperhatikan huruf besar dan kecil, perilakunya bergantung pada sistem berkas tempat pencarian dilakukan.

Penelusuran rekursif dengan rglob#

Metode rglob() berperilaku seperti glob(), tetapi menelusuri seluruh subdirektori di bawah titik awalnya, sedalam-dalamnya, dan setara dengan pola "**/..." pada glob(). Metode ini tepat untuk struktur berlapis seperti arsip tahunan yang berkasnya tersebar di banyak tingkat folder. Ukuran setiap berkas yang ditemukan dibaca melalui stat().st_size tanpa membuka isinya.

Penelusuran yang dalam memakan waktu sebanding dengan jumlah berkas yang dikunjungi, sehingga polanya sebaiknya dipersempit sedini mungkin pada pohon direktori yang besar. Pola rglob("*.csv") lebih hemat daripada mengambil seluruh berkas lalu menyaringnya sendiri dengan Python, karena penyaringan dilakukan oleh proses penelusuran itu sendiri. Untuk struktur yang sudah diketahui kedalamannya, glob() pada jalur yang lebih spesifik tetap menjadi pilihan yang paling ringan.

python Contoh: penelusuran rekursif dengan rglob
from pathlib import Path

root = Path("arsip")
(root / "2024").mkdir(parents=True, exist_ok=True)
(root / "2025").mkdir(parents=True, exist_ok=True)
(root / "2024" / "q1.txt").write_text("Q1\n", encoding="utf-8")
(root / "2025" / "q2.txt").write_text("Q2\n", encoding="utf-8")
(root / "2025" / "q3.txt").write_text("Q3\n", encoding="utf-8")
for f in sorted(root.rglob("*.txt")):
    print(f, f.stat().st_size, "byte")
text Keluaran
arsip/2024/q1.txt 3 byte
arsip/2025/q2.txt 3 byte
arsip/2025/q3.txt 3 byte
python Contoh: iterdir dan uji jenis jalur
from pathlib import Path

root = Path("arsip")
print([f.name for f in sorted(root.iterdir())])
q2 = root / "2025" / "q2.txt"
print(q2.is_file(), (root / "2024").is_dir(), (root / "2025" / "q9.txt").is_file())
text Keluaran
['2024', '2025']
True True False

Metode iterdir() menampilkan isi langsung satu direktori tanpa turun ke bawah, sehingga hanya 2024 dan 2025 yang terdaftar. Metode is_file() dan is_dir() menguji jenis jalur tanpa membaca apa pun, dan keduanya mengembalikan False untuk jalur yang tidak ada alih-alih menimbulkan error. Sifat ini membuat kedua metode tersebut lazim dipakai sebagai pemeriksaan awal sebelum berkas diproses.

Kesalahan umum#

Kesalahan pertama adalah mengandalkan urutan hasil glob() dan rglob() tanpa pengurutan. Urutan yang dikembalikan bergantung pada sistem berkas, sehingga program yang sama dapat menghasilkan urutan berbeda di mesin lain. Perbaikannya adalah membungkus hasilnya dengan sorted(), sebagaimana dilakukan pada seluruh contoh di atas, atau mengurutkan berdasarkan atribut tertentu melalui argumen key.

Kesalahan kedua adalah menyusun jalur melalui penyambungan string biasa. Hasilnya mudah salah karena pemisah direktori harus ditebak secara manual, sedangkan operator / milik Path menempatkan pemisah tersebut dengan benar. Ekspresi root / "2025" / "q2.txt" tetap benar dengan atau tanpa garis miring di ujung tiap bagiannya.

Kesalahan ketiga adalah mengira glob("*.csv") juga menemukan berkas di dalam subdirektori. Pola tersebut hanya memeriksa satu tingkat, sehingga pencarian yang butuh kedalaman penuh harus memakai rglob() atau pola "**/*.csv". Kesalahan terakhir yang lazim adalah menghapus berkas dengan unlink() sebelum memastikan isinya sudah dipindahkan, karena penghapusan pada sistem berkas tidak melewati keranjang sampah.

Ringkasan#

  • Path merepresentasikan jalur sebagai objek dengan operator / penyambung serta atribut name, stem, suffix, dan parent.
  • Metode read_text() dan write_text() menangani pembacaan dan penulisan berkas dalam satu pemanggilan, sedangkan unlink() menghapus berkasnya.
  • glob() mencari berkas berdasarkan pola pada satu direktori, sedangkan rglob() menelusuri seluruh subdirektori di bawah titik awalnya.
  • Urutan hasil pencarian tidak dijamin, sehingga hasilnya selalu diurutkan dengan sorted() sebelum digunakan.

Referensi#