IO #
Hampir semua program nyata perlu berinteraksi dengan sistem file — membaca konfigurasi, menyimpan hasil, memproses data dari CSV, atau menulis log. Python menyediakan beberapa lapisan untuk operasi ini: fungsi bawaan open() untuk akses file langsung, modul pathlib untuk navigasi path secara modern, modul os dan shutil untuk manipulasi sistem file, serta modul csv dan json untuk format data yang umum. Memahami kapan menggunakan masing-masing akan membuat kode kamu lebih bersih dan lebih aman.
Membaca dan Menulis File #
Fungsi open() adalah pintu utama untuk bekerja dengan file. Selalu gunakan with statement agar file otomatis ditutup meski terjadi error.
# ANTI-PATTERN: membuka file tanpa with
f = open("data.txt", "r")
konten = f.read()
f.close() # -- jika ada error sebelum ini, file tidak pernah ditutup
# BENAR: gunakan with statement
with open("data.txt", "r") as f:
konten = f.read()
# file otomatis ditutup di sini, bahkan jika ada exception
Mode Buka File #
# Mode yang paling sering digunakan:
open("file.txt", "r") # read -- default, file harus ada
open("file.txt", "w") # write -- buat baru atau timpa isi
open("file.txt", "a") # append -- tambah di akhir, buat jika belum ada
open("file.txt", "x") # exclusive -- buat baru, error jika sudah ada
open("file.txt", "rb") # read binary
open("file.txt", "wb") # write binary
Membaca File #
# Baca seluruh isi sekaligus
with open("data.txt", "r", encoding="utf-8") as f:
isi = f.read()
# Baca baris per baris -- efisien untuk file besar
with open("data.txt", "r", encoding="utf-8") as f:
for baris in f:
print(baris.rstrip("\n"))
# Baca semua baris ke dalam list
with open("data.txt", "r", encoding="utf-8") as f:
semua_baris = f.readlines()
# readline() -- baca satu baris
with open("data.txt", "r", encoding="utf-8") as f:
baris_pertama = f.readline()
Menulis File #
baris = ["baris pertama", "baris kedua", "baris ketiga"]
# Tulis string
with open("output.txt", "w", encoding="utf-8") as f:
f.write("Hello, world!\n")
# Tulis banyak baris sekaligus
with open("output.txt", "w", encoding="utf-8") as f:
f.writelines(f"{b}\n" for b in baris)
# Append -- tambah ke akhir file yang sudah ada
with open("log.txt", "a", encoding="utf-8") as f:
f.write("Entry log baru\n")
Selalu tentukanencoding="utf-8"secara eksplisit saat membuka file teks. Encoding default bervariasi tergantung sistem operasi — Windows sering menggunakancp1252ataulatin-1, yang bisa menyebabkan error saat teks berisi karakter non-ASCII seperti huruf beraksara.
Membaca File Biner #
# Baca file gambar atau file biner lainnya
with open("gambar.png", "rb") as f:
data = f.read()
# Salin file biner secara manual
with open("sumber.bin", "rb") as src, open("tujuan.bin", "wb") as dst:
while chunk := src.read(8192): # baca per 8KB
dst.write(chunk)
pathlib — Navigasi Path Modern #
Modul pathlib (Python 3.4+) adalah cara yang direkomendasikan untuk bekerja dengan path sistem file. Ia memodelkan path sebagai objek, bukan string, sehingga operasi path menjadi lebih intuitif dan lintas platform.
from pathlib import Path
# Buat objek Path
p = Path("dokumen/laporan.txt")
home = Path.home() # direktori home user
cwd = Path.cwd() # direktori kerja saat ini
# Navigasi path dengan operator /
project_dir = Path("/home/user/project")
config_file = project_dir / "config" / "settings.json"
print(config_file) # /home/user/project/config/settings.json
Properti Path yang Berguna #
p = Path("/home/user/dokumen/laporan.pdf")
print(p.name) # "laporan.pdf" -- nama file lengkap
print(p.stem) # "laporan" -- nama tanpa ekstensi
print(p.suffix) # ".pdf" -- ekstensi
print(p.suffixes) # [".pdf"] -- semua ekstensi (untuk .tar.gz → ['.tar', '.gz'])
print(p.parent) # /home/user/dokumen -- direktori induk
print(p.parts) # ('/', 'home', 'user', 'dokumen', 'laporan.pdf')
Operasi File dengan pathlib #
from pathlib import Path
p = Path("data.txt")
# Cek keberadaan
print(p.exists()) # True / False
print(p.is_file()) # True jika file
print(p.is_dir()) # True jika direktori
# Baca dan tulis langsung
p.write_text("Isi file", encoding="utf-8")
isi = p.read_text(encoding="utf-8")
p_biner = Path("data.bin")
p_biner.write_bytes(b"\x00\x01\x02")
data = p_biner.read_bytes()
# Ubah nama / pindahkan
p.rename(Path("data_baru.txt"))
# Hapus file
p.unlink()
p.unlink(missing_ok=True) # tidak error jika file tidak ada (Python 3.8+)
Membuat dan Menghapus Direktori #
from pathlib import Path
# Buat direktori
Path("direktori_baru").mkdir()
Path("a/b/c").mkdir(parents=True, exist_ok=True) # buat semua level, tidak error jika sudah ada
# Hapus direktori kosong
Path("direktori_baru").rmdir()
# List isi direktori
p = Path(".")
for item in p.iterdir():
print(item)
# Glob -- cari file dengan pola
for f in Path(".").glob("*.txt"):
print(f)
for f in Path(".").rglob("*.py"): # rekursif
print(f)
Gunakanpathlibuntuk semua operasi path di kode baru. Ia lebih bersih dari penggabungan string manual (os.path.join()), lintas platform secara otomatis, dan langsung bisa digunakan denganopen().
Modul os — Interaksi Sistem Operasi
#
Modul os memberikan akses ke fungsi sistem operasi tingkat rendah. Untuk manipulasi path, pathlib lebih direkomendasikan, tapi os masih diperlukan untuk beberapa operasi seperti environment variable dan informasi proses.
import os
# Environment variable
home_dir = os.environ.get("HOME", "/tmp")
db_url = os.environ.get("DATABASE_URL") # None jika tidak ada
# Direktori kerja
print(os.getcwd()) # direktori saat ini
os.chdir("/tmp") # pindah direktori
# Informasi file
stat = os.stat("data.txt")
print(stat.st_size) # ukuran file dalam bytes
print(stat.st_mtime) # waktu modifikasi terakhir (Unix timestamp)
# Jalankan perintah sistem
exit_code = os.system("ls -la")
os.path untuk Operasi Path
#
import os
# ANTI-PATTERN: gabungkan path dengan string
path = "/home/user" + "/" + "dokumen" + "/" + "file.txt"
# BENAR: gunakan os.path.join() atau lebih baik pathlib
path = os.path.join("/home/user", "dokumen", "file.txt")
print(os.path.exists(path)) # cek keberadaan
print(os.path.isfile(path)) # cek apakah file
print(os.path.isdir("/home/user")) # cek apakah direktori
print(os.path.basename(path)) # "file.txt"
print(os.path.dirname(path)) # "/home/user/dokumen"
print(os.path.splitext("file.txt")) # ("file", ".txt")
print(os.path.getsize(path)) # ukuran dalam bytes
Manipulasi File dan Direktori dengan os
#
import os
os.mkdir("direktori_baru") # buat direktori (satu level)
os.makedirs("a/b/c", exist_ok=True) # buat semua level
os.rename("lama.txt", "baru.txt") # ubah nama / pindahkan
os.remove("file_yang_mau_dihapus.txt") # hapus file
os.rmdir("direktori_kosong") # hapus direktori kosong
isi = os.listdir(".") # list isi direktori
Modul shutil — Operasi File Tingkat Tinggi
#
shutil (shell utilities) menyediakan fungsi untuk operasi yang lebih kompleks seperti menyalin direktori beserta isinya atau menghapus direktori yang tidak kosong.
import shutil
# Salin file
shutil.copy("sumber.txt", "tujuan.txt") # salin file + permission
shutil.copy2("sumber.txt", "tujuan.txt") # salin file + metadata lengkap
shutil.copyfile("sumber.txt", "tujuan.txt") # salin isi saja
# Salin direktori beserta isinya
shutil.copytree("src_dir", "dst_dir")
shutil.copytree("src_dir", "dst_dir", dirs_exist_ok=True) # Python 3.8+
# Pindahkan file atau direktori
shutil.move("sumber.txt", "direktori_tujuan/")
shutil.move("folder_lama", "folder_baru")
# Hapus direktori beserta seluruh isinya
shutil.rmtree("direktori_yang_mau_dihapus")
shutil.rmtree() menghapus direktori dan seluruh isinya secara permanen tanpa konfirmasi. Pastikan path yang diberikan sudah benar sebelum menjalankan fungsi ini.Modul json — Baca Tulis JSON
#
JSON adalah format pertukaran data yang paling umum. Modul json bawaan Python sudah cukup untuk sebagian besar kebutuhan.
import json
data = {
"nama": "Budi",
"usia": 28,
"hobi": ["membaca", "coding"],
"aktif": True
}
# Encode Python → JSON string
json_str = json.dumps(data)
print(json_str)
# {"nama": "Budi", "usia": 28, "hobi": ["membaca", "coding"], "aktif": true}
# Pretty print
print(json.dumps(data, indent=2, ensure_ascii=False))
# Decode JSON string → Python
kembali = json.loads(json_str)
print(kembali["nama"]) # "Budi"
Baca Tulis JSON ke File #
import json
data = {"konfigurasi": {"debug": False, "port": 8080}}
# Tulis ke file
with open("config.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
# Baca dari file
with open("config.json", "r", encoding="utf-8") as f:
config = json.load(f)
print(config["konfigurasi"]["port"]) # 8080
Menangani Tipe Data Non-Standar #
import json
from datetime import datetime
# ANTI-PATTERN: datetime tidak bisa di-serialize langsung
data = {"timestamp": datetime.now()}
# json.dumps(data) # TypeError: Object of type datetime is not JSON serializable
# BENAR: konversi manual atau gunakan custom encoder
data = {"timestamp": datetime.now().isoformat()}
print(json.dumps(data)) # {"timestamp": "2024-01-15T10:30:00.123456"}
Modul csv — Baca Tulis CSV
#
Modul csv menangani parsing CSV dengan benar, termasuk kasus seperti nilai yang mengandung koma atau tanda kutip.
import csv
# Tulis CSV
baris_data = [
["nama", "usia", "kota"],
["Alice", 25, "Jakarta"],
["Bob", 30, "Bandung"],
]
with open("data.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerows(baris_data)
# Baca CSV
with open("data.csv", "r", encoding="utf-8") as f:
reader = csv.reader(f)
for baris in reader:
print(baris)
# ['nama', 'usia', 'kota']
# ['Alice', '25', 'Jakarta']
# ['Bob', '30', 'Bandung']
DictReader dan DictWriter #
DictReader dan DictWriter lebih nyaman karena menggunakan header sebagai key dictionary, sehingga kamu tidak perlu mengingat urutan kolom.
import csv
# DictWriter -- tulis dengan nama kolom
fieldnames = ["nama", "usia", "kota"]
with open("data.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows([
{"nama": "Alice", "usia": 25, "kota": "Jakarta"},
{"nama": "Bob", "usia": 30, "kota": "Bandung"},
])
# DictReader -- baca sebagai dictionary
with open("data.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for baris in reader:
print(f"{baris['nama']} tinggal di {baris['kota']}")
# Alice tinggal di Jakarta
# Bob tinggal di Bandung
Selalu gunakannewline=""saat membuka file CSV di Windows. Tanpa ini, setiap baris akan diakhiri dengan\r\r\n(double carriage return) yang menyebabkan baris kosong di antara setiap baris data.
Modul io — IO Berbasis Memori
#
Modul io menyediakan StringIO dan BytesIO — objek yang berperilaku seperti file tapi hidup di memori. Berguna untuk testing, memproses data yang belum perlu disimpan ke disk, atau saat API mengharapkan file object.
import io
# StringIO -- file teks di memori
buffer = io.StringIO()
buffer.write("baris pertama\n")
buffer.write("baris kedua\n")
print(buffer.getvalue())
# baris pertama
# baris kedua
# Gunakan sebagai file object
buffer.seek(0) # kembali ke awal
for baris in buffer:
print(baris.rstrip())
# BytesIO -- file biner di memori
data_biner = io.BytesIO(b"\x89PNG\r\n\x1a\n")
print(data_biner.read(4)) # b'\x89PNG'
Penggunaan nyata StringIO — menguji fungsi yang mengharapkan file object tanpa membuat file sungguhan:
import io
import csv
def proses_csv(file_obj):
reader = csv.DictReader(file_obj)
return [baris["nama"] for baris in reader]
# Gunakan StringIO sebagai pengganti file sungguhan saat testing
data_csv = "nama,usia\nAlice,25\nBob,30"
hasil = proses_csv(io.StringIO(data_csv))
print(hasil) # ['Alice', 'Bob']
Kapan Pakai Apa #
Perlu membaca/menulis file teks atau biner?
✓ Gunakan open() dengan with statement
Perlu bekerja dengan path (navigasi, cek keberadaan, glob)?
✓ Gunakan pathlib.Path -- modern, lintas platform, direkomendasikan
✓ Gunakan os.path -- jika perlu kompatibilitas Python lama
Perlu menyalin atau menghapus direktori beserta isinya?
✓ Gunakan shutil.copytree() / shutil.rmtree()
Perlu membaca environment variable atau info proses?
✓ Gunakan os.environ
Perlu bekerja dengan data JSON?
✓ Gunakan modul json
Perlu bekerja dengan data CSV?
✓ Gunakan csv.DictReader / csv.DictWriter
Perlu file object tapi tidak mau nulis ke disk (testing, buffer)?
✓ Gunakan io.StringIO atau io.BytesIO
Ringkasan #
- Selalu gunakan
withstatement saat membuka file — file otomatis ditutup meski ada error.- Selalu tentukan
encoding="utf-8"secara eksplisit untuk file teks agar perilaku konsisten di semua platform.pathlibadalah cara modern dan direkomendasikan untuk bekerja dengan path — lebih bersih darios.pathdan operator/menggantikanos.path.join().shutil.rmtree()menghapus permanen tanpa konfirmasi — pastikan path sudah benar sebelum dijalankan.csv.DictReader/csv.DictWriterlebih baik daricsv.reader/csv.writerbiasa karena mengakses kolom berdasarkan nama, bukan indeks.json.dumps()/json.loads()untuk serialisasi ke/dari string;json.dump()/json.load()untuk ke/dari file langsung.io.StringIOdanio.BytesIOberguna untuk testing dan memproses data di memori tanpa menyentuh disk.