File YAML ada di mana-mana: docker-compose.yml, workflow GitHub Actions, manifest Kubernetes, sampai playbook Ansible semuanya pakai format yang sama. Kalau kamu kerja di backend atau DevOps, cepat atau lambat kamu akan butuh membaca file semacam itu dari Python — entah untuk menarik satu nilai konfigurasi atau men-generate file deployment otomatis. PyYAML adalah library standar untuk urusan ini, dan pemakaiannya sebenarnya simpel. Yang bikin banyak orang celaka cuma satu: cara mereka memanggil loader-nya.
Install PyYAML
PyYAML tidak ikut dalam standard library Python, jadi install dulu lewat pip. Versi terbaru sudah mendukung Python 3.13, jadi tidak ada alasan untuk bertahan di versi lama.
pip install pyyaml
Cek versi yang terpasang biar yakin semuanya beres:
python -c "import yaml; print(yaml.__version__)"
Membaca file YAML dengan safe_load
Mulai dari kasus paling umum: kamu punya file config.yaml dan mau mengambil nilainya di Python. Buat dulu file-nya seperti ini:
# config.yaml
server:
host: 0.0.0.0
port: 8000
debug: false
database:
name: bengkelkode
user: admin
Lalu baca pakai safe_load:
import yaml
with open("config.yaml", "r", encoding="utf-8") as f:
config = yaml.safe_load(f)
print(config["server"]["host"]) # 0.0.0.0
print(config["database"]["name"]) # bengkelkode
print(config["server"]["port"]) # 8000 -> int
print(type(config["server"]["debug"])) # <class 'bool'>
Perhatikan tipe datanya. PyYAML otomatis mengubah port: 8000 jadi int dan debug: false jadi bool False. Ini nyaman, tapi bisa menggigit kalau kamu tidak sadar — nomor telepon yang ditulis 08123456789 akan dibaca sebagai integer dan angka nol di depannya hilang. Untuk nilai semacam itu, tulis angkanya dalam tanda kutip di file YAML.
Menulis YAML dari Python dengan dump
Arah sebaliknya juga sering dipakai: kamu punya data di Python dan mau menulisnya ke file YAML supaya bisa dibaca manusia atau tool lain. Pakai yaml.dump:
import yaml
data = {
"server": {"host": "0.0.0.0", "port": 8000, "debug": False},
"database": {"name": "bengkelkode", "user": "admin"},
"features": ["blog", "newsletter", "search"],
}
with open("output.yaml", "w", encoding="utf-8") as f:
yaml.dump(data, f, sort_keys=False, default_flow_style=False)
server:
host: 0.0.0.0
port: 8000
debug: false
database:
name: bengkelkode
user: admin
features:
- blog
- newsletter
- search
default_flow_style=False membuat output pakai blok ber-indentasi alih-alih gaya JSON satu baris, dan sort_keys=False mempertahankan urutan key yang kamu definisikan. Tanpa sort_keys=False, key diurutkan alfabetis dan susunan aslimu berantakan.
Jangan pernah pakai yaml.load()
Ini bagian paling penting di seluruh artikel. Banyak tutorial YAML di internet masih menulis yaml.load(...). Itu berbahaya.
Loader default yaml.load() bisa mengeksekusi objek Python sembarang. Artinya, kalau aplikasimu membaca YAML dari sumber yang tidak kamu percayai — upload user, respons API pihak ketiga — penyerang bisa menyisipkan payload yang menjalankan perintah sistem.
import yaml
# JANGAN dijalankan di mesin penting — ini bukti kenapa yaml.load() berbahaya.
payload = "!!python/object/apply:os.system ['id']"
yaml.unsafe_load(payload) # setara yaml.load(payload, Loader=yaml.Loader)
Jalankan itu dan kamu akan melihat hasil perintah id dieksekusi oleh proses Python-mu. PyYAML sudah lama menyediakan jalan aman: safe_load() dan safe_dump() hanya mendukung tipe data standar — dict, list, str, int, float, bool, None, dan tanggal — lalu menolak tag objek Python. Selalu pakai safe_load.
Aturan praktis: kalau kamu menulis yaml.load, yaml.full_load, atau yaml.unsafe_load tanpa alasan yang sangat jelas, berhenti dan ganti ke yaml.safe_load. Kalau kamu benar-benar butuh fitur objek Python, sadari bahwa kamu sedang membuka pintu eksekusi kode.
Multi-dokumen, anchor, dan struktur rumit
YAML punya beberapa fitur yang jarang dibahas tapi berguna saat ketemu di proyek orang lain. Anchor (&nama) dan alias (*nama) memungkinkan kamu mewariskan blok konfigurasi tanpa copy-paste:
import yaml
doc = """
defaults: &defaults
timeout: 30
retries: 3
production:
<<: *defaults
host: prod.bengkelkode.com
staging:
<<: *defaults
host: staging.bengkelkode.com
"""
config = yaml.safe_load(doc)
print(config["production"]["timeout"]) # 30 (diwarisi dari defaults)
print(config["staging"]["host"]) # staging.bengkelkode.com
Satu file YAML juga bisa berisi beberapa dokumen yang dipisahkan oleh ---. Pakai safe_load_all untuk membacanya satu per satu:
import yaml
stream = """
---
nama: dokumen pertama
---
nama: dokumen kedua
"""
for dok in yaml.safe_load_all(stream):
print(dok["nama"])
Mengatur format output
Saat menulis YAML, beberapa opsi sering menyelamatkan. allow_unicode=True mencegah karakter non-ASCII di-escape jadi \uXXXX, sort_keys=False menjaga urutan, dan indent menentukan lebar indentasi. Kalau kamu generate file untuk playbook Ansible, format blok seperti ini jauh lebih enak dibaca ketimbang satu baris penuh.
import yaml
data = {
"nama": "BengkelKode",
"deskripsi": "Tutorial coding berbahasa Indonesia",
"tahun": 2026,
}
print(yaml.dump(data, allow_unicode=True, sort_keys=False, indent=4))
nama: BengkelKode
deskripsi: Tutorial coding berbahasa Indonesia
tahun: 2026
Dari YAML ke konfigurasi aplikasi yang valid
Membaca YAML saja tidak cukup kalau file-nya bisa berisi key yang salah atau nilai dengan tipe keliru. Setelah safe_load, validasi hasilnya sebelum dipakai — entah manual atau pakai library seperti Pydantic untuk memetakan dict ke model bertipe. Ini menghindari error yang baru muncul saat aplikasi sudah berjalan di produksi.
safe_load mengembalikan dict Python biasa. Validasi hasilnya dengan Pydantic sebelum dipakai, supaya konfigurasi yang salah ketahuan saat startup — bukan jam 2 pagi di produksi.
Mulai dari proyek yang sudah ada: ganti semua pemanggilan yaml.load() di kodebasemu dengan yaml.safe_load(), lalu tulis satu fungsi kecil yang membaca file config dan memvalidasinya sebelum aplikasi jalan. Kebiasaan itu bayarannya besar dan ongkosnya cuma beberapa menit.