Satu kode pipeline biasanya berjalan di tiga tempat: laptop saat pengembangan, server staging untuk pengujian, dan server production dengan data nyata. Alamat database, tingkat log, dan ukuran batch pasti berbeda antar ketiganya. Bila nilai-nilai tersebut ditulis permanen di dalam kode, setiap deployment menuntut pengubahan kode dan membuka peluang kelalaian. Environment variable menjadi jembatannya: kode membaca pengaturan dari luar, sedangkan setiap lingkungan menyuplai nilai yang sesuai.

Membaca Environment Variable dari Python #

Modul os menyediakan dua pintu baca. Akses os.environ mengambil dari kamus variabel proses, sedangkan fungsi os.getenv() menambahkan kemudahan berupa nilai bawaan (default) saat variabel belum diatur:

python
import os

# Membaca environment variable dengan os.environ
print("USER :", os.environ.get("USER"))

# os.getenv dengan nilai bawaan bila variable belum diatur
print("APP_ENV :", os.getenv("APP_ENV", "belum diatur"))
print("LOG_LEVEL :", os.getenv("LOG_LEVEL", "INFO"))
print("MAX_RETRIES :", os.getenv("MAX_RETRIES", "3"))

Output yang Dihasilkan:

text
USER : z
APP_ENV : belum diatur
LOG_LEVEL : INFO
MAX_RETRIES : 3

Variabel USER memang sudah diatur oleh sistem sehingga nilainya tercetak. Sebaliknya, APP_ENV belum diatur, sehingga nilai bawaan "belum diatur" yang muncul. Kita juga dapat menetapkan variabel hanya untuk satu kali eksekusi, dengan menuliskannya di depan perintah:

bash
APP_ENV=production python3 baca_env.py

Output yang Dihasilkan:

text
USER : z
APP_ENV : production
LOG_LEVEL : INFO
MAX_RETRIES : 3

Hanya baris APP_ENV yang berubah menjadi production — variabel tersebut hanya hidup selama proses Python berjalan dan tidak mengubah pengaturan shell secara permanen. Dokumentasi lengkap kedua fungsi tersebut ada di https://docs.python.org/3/library/os.html .

Berkas .env dan python-dotenv #

Mengetik variabel panjang di depan setiap perintah lelah dibaca. Praktik umum: simpan pasangan kunci-nilai di berkas .env pada akar proyek, lalu muat dengan pustaka python-dotenv (pasang lewat pip install python-dotenv). Misalnya berkas .env berikut:

text Isi .env
APP_ENV=development
WAREHOUSE_DB_URL=postgresql://budi:YOUR_DATABASE_PASSWORD@localhost:5432/penjualan
LOG_LEVEL=INFO

Skrip pembacanya menjadi ringkas:

python
from dotenv import load_dotenv
import os

# Muat berkas .env dari direktori kerja saat ini
load_dotenv()

print("APP_ENV         :", os.getenv("APP_ENV"))
print("WAREHOUSE_DB_URL:", os.getenv("WAREHOUSE_DB_URL"))
print("LOG_LEVEL       :", os.getenv("LOG_LEVEL"))

Output yang Dihasilkan:

text
APP_ENV         : development
WAREHOUSE_DB_URL: postgresql://budi:YOUR_DATABASE_PASSWORD@localhost:5432/penjualan
LOG_LEVEL       : INFO

Mari kita telaah baris-baris kode di atas:

  1. Baris 1 (from dotenv import load_dotenv): mengimpor fungsi pemuat dari pustaka python-dotenv.
  2. Baris 5 (load_dotenv()): membaca berkas .env di folder kerja, mengurai setiap baris KUNCI=nilai, lalu mendaftarkannya ke environment variable proses.
  3. Baris 7-9 (os.getenv(...)): membaca variabel yang barusan didaftarkan dengan pola yang sama seperti contoh sebelumnya.

Perilaku Penimpaan load_dotenv #

Secara bawaan, load_dotenv() tidak menimpa variabel yang sudah terlebih dahulu diatur di shell. Skrip berikut diuji pada mesin yang variabel DATABASE_URL-nya sudah berisi nilai lain, sementara berkas .env menyimpan nilai PostgreSQL:

python
from dotenv import load_dotenv
import os

# DATABASE_URL sudah diatur di shell sebelum skrip berjalan.
# Secara bawaan load_dotenv() TIDAK menimpa nilai yang sudah ada.
load_dotenv()
print("tanpa override  :", os.getenv("DATABASE_URL"))

# Dengan override=True, nilai dari .env menimpa nilai dari shell.
load_dotenv(override=True)
print("dengan override :", os.getenv("DATABASE_URL"))

Output yang Dihasilkan:

text
tanpa override  : file:/home/z/my-project/db/custom.db
dengan override : postgresql://budi:YOUR_DATABASE_PASSWORD@localhost:5432/penjualan

Baris pertama membuktikan nilai shell tetap dipakai meskipun .env menyimpan nilai lain. Baris kedua menunjukkan parameter override=True membalik perilaku tersebut. Perilaku bawaan justru berguna di production: variabel yang diatur orchestrator selalu menang atas berkas .env yang mungkin lupa diperbarui.

Konfigurasi per Lingkungan #

Dengan pola di atas, satu kode cukup membaca APP_ENV lalu menyesuaikan diri. Perbedaan nilai antar lingkungan biasanya terpetakan rapi seperti tabel berikut:

Aspekdevelopmentstagingproduction
APP_ENVdevelopmentstagingproduction
Basis dataSQLite lokalPostgreSQL stagingwarehouse production
LOG_LEVELDEBUGINFOWARNING
Isi datasampel kecilsalinan tanpa data pribadidata nyata

Setiap lingkungan memiliki berkas .env versinya sendiri (atau sekumpulan variabel di sistem orchestrator), dan nilai APP_ENV menjadi saklar yang menentukan perilaku kode. Rincian pustaka python-dotenv tersedia di https://pypi.org/project/python-dotenv/ .

Berkas .env menuntut tata letak proyek yang rapi agar tidak tertukar antar lingkungan. Tata letak tersebut kita susun pada chapter Struktur Proyek Data Engineering.