Hampir setiap program serius membaca konfigurasi dari luar kode: alamat database, batas retry, mode debug. Selama bertahun-tahun ekosistem Python terpecah antara INI, JSON, dan YAML — sampai komunitas bertemu TOML dan menjadikannya standar de facto lewat pyproject.toml. Python 3.11 akhirnya menyertakan pembaca TOML di standard library: module tomllib. Pada Chapter ini kita akan membaca file TOML dengan tomllib, memetakan sintaks TOML yang wajib dikenal, dan memilih format konfigurasi secara sadar.

Parsing dengan load dan loads #

Module tomllib menyediakan dua pintu: loads() untuk string TOML dan load() untuk file biner. Hasil keduanya adalah struktur Python biasa — dictionary, list, string, angka, boolean, serta tipe tanggal:

python
import tomllib

toml_teks = """
judul = "konfigurasi layanan"
diluncurkan = 2025-06-15T10:30:00Z

[server]
host = "db.example.com"
port = 5432
aktif = true
tag = ["produksi", "utama"]

[server.pemilik]
nama = "Budi"
email = "[email protected]"
"""

data = tomllib.loads(toml_teks)
print(data["judul"])
print(data["diluncurkan"])
print(data["server"]["host"], "port", data["server"]["port"])
print(data["server"]["tag"])
print(data["server"]["pemilik"]["nama"])

Output yang Dihasilkan:

text
konfigurasi layanan
2025-06-15 10:30:00+00:00
db.example.com port 5432
['produksi', 'utama']
Budi

Mari kita bedah pemetaan yang dilakukan parser tomllib:

  1. Baris judul = "...": pasangan kunci-nilai sebelum header tabel apa pun menjadi item pada dictionary paling atas.
  2. Baris diluncurkan = 2025-06-15T10:30:00Z: TOML memiliki tipe datetime asli; parser mengembalikan objek datetime dari module datetime yang sadar zona waktu (+00:00 menandakan UTC), bukan string.
  3. Baris [server]: header tabel membuat sub-dictionary data["server"]; pasangan di bawahnya menjadi anggota tabel tersebut.
  4. Baris [server.pemilik]: header bertitik membuat tabel bersarang data["server"]["pemilik"] tanpa perlu deklarasi [server] terpisah — keduanya bisa hadir berurutan seperti contoh.

Esensi sintaks TOML dirangkum pada tabel berikut:

Elemen TOMLSintaksHasil di Python
Pasangan kunci-nilaiport = 5432{"port": 5432}
Tabel[server]{"server": {...}}
Tabel bersarang[server.pemilik]dict di dalam dict
Arraytag = ["produksi", "utama"]list
Inline tabletitik = {x = 1, y = 2}dict satu baris
Array of tables[[produk]]list berisi dict
Tanggaldiluncurkan = 2025-06-15datetime.date / datetime
Booleanaktif = trueTrue (huruf kecil)

Membaca File Konfigurasi Nyata #

Untuk file di disk, gunakan tomllib.load() dengan mode biner — load() menolak mode teks karena parser tomllib membaca bytes:

python
import tomllib
from pathlib import Path

isi_toml = """
[aplikasi]
nama = "kasir"
versi = "1.2.0"

[pengguna]
max_login = 3
"""

path = Path("konfigurasi.toml")
path.write_text(isi_toml, encoding="utf-8")

with open(path, "rb") as berkas:  # tomllib.load wajib mode biner
    data = tomllib.load(berkas)

print(data["aplikasi"]["nama"], "versi", data["aplikasi"]["versi"])
print("maksimum login:", data["pengguna"]["max_login"])

path.unlink()

Output yang Dihasilkan:

text
kasir versi 1.2.0
maksimum login: 3

Skrip di atas menulis file konfigurasi lebih dulu agar contoh berdiri sendiri; pada proyek nyata, file konfigurasi.toml sudah ada di disk dan kita cukup membacanya. Galat pada file (tipe tidak cocok, kurung tidak seimbang) dinaikkan sebagai tomllib.TOMLDecodeError — subclass ValueError — sehingga bisa ditangkap dengan pola try/except biasa dari Chapter Memahami Exceptions.

pyproject.toml sebagai Contoh Unggulan #

Sekarang kita lihat mengapa TOML menang: file pyproject.toml yang sama rapi dibaca oleh pip dan tool lain. Contoh metadata package berikut (topik lengkapnya ada pada Chapter pyproject.toml) menunjukkan campuran skenario nyata — tabel bertingkat dan array string:

python
import tomllib

pyproject = """
[project]
name = "alat-kasir"
version = "0.3.1"
requires-python = ">=3.12"
dependencies = ["httpx", "rich"]

[tool.ruff]
line-length = 100
"""

meta = tomllib.loads(pyproject)
print(meta["project"]["name"], meta["project"]["version"])
print("butuh Python", meta["project"]["requires-python"])
print("dependensi:", meta["project"]["dependencies"])
print("ruff line-length:", meta["tool"]["ruff"]["line-length"])

Output yang Dihasilkan:

text
alat-kasir 0.3.1
butuh Python >=3.12
dependensi: ['httpx', 'rich']
ruff line-length: 100

Konvensi [tool.<nama>] pada pyproject.toml memberi setiap tool tabel konfigurasinya sendiri; tomllib membaca semuanya sebagai dictionary biasa tanpa kejutan.

TOML vs JSON vs YAML vs INI #

AspekTOMLJSONYAMLINI (configparser)
KomentarYa (#)TidakYaYa
Tipe dataLengkap (tanggal, array, inline table)Lengkap, tanpa komentarLengkap, plus jangkarSemua string
Kesalahan umumKurung tidak seimbangKoma/kutip terlupakanIndentasi, implicit typing (no → False)Struktur datar
Edit manualNyamanKurang nyamanNyaman, rawan silapNyaman, terbatas
Writer stdlibTidakYa (json.dump)TidakYa (configparser.write)