BashOperator dan PythonOperator adalah dua operator yang paling sering digunakan pada gaya klasik penulisan DAG. Topik ini membahas parameter utama kedua operator, perbedaan gaya klasik dengan TaskFlow API, serta pelaksanaan DAG klasik hingga seluruh task berstatus success. Gaya klasik tetap penting untuk dikuasai karena banyak contoh, dokumentasi operator, dan kode lama masih menggunakan bentuk ini.
BashOperator#
BashOperator menjalankan satu perintah shell melalui parameter bash_command. Perintah tersebut dieksekusi di lingkungan kerja task. Status akhir task mengikuti exit code perintahnya, yaitu kode numerik yang ditinggalkan proses perintah saat berakhir. Perintah yang berakhir dengan exit code nol menandakan task success, sedangkan exit code selain nol menandai task failed, dengan pesan error yang tercatat pada log. Perilaku ini membuat BashOperator cocok untuk membungkus skrip shell yang sudah ada, misalnya skrip arsip cadangan berkas atau pembersihan folder sementara.
Parameter env menyediakan variabel lingkungan khusus untuk proses yang menjalankan perintah shell. Isinya berupa kamus, misalnya env={"KOTA": "Bandung"}, dan nilainya dirujuk oleh perintah shell sebagaimana variabel lingkungan biasa. Secara bawaan, kamus ini menggantikan lingkungan proses Airflow, sehingga variabel lain tidak terbawa ke proses perintah. Dengan append_env=True, lingkungan proses Airflow tetap diwarisi, sedangkan isi env diletakkan di atasnya. Kombinasi bash_command dan env menjadi cara ringkas mengirim konfigurasi kecil tanpa menyunting teks perintahnya.
PythonOperator#
PythonOperator memanggil fungsi Python melalui parameter python_callable. Fungsi yang dirujuk harus didefinisikan pada level modul berkas DAG, yaitu langsung di badan berkas dan bukan di dalam fungsi lain. Dengan letak seperti itu, fungsi dapat diimpor oleh proses yang menjalankan task. Argumen fungsi dikirim melalui op_args untuk argumen posisi atau op_kwargs untuk argumen kata kunci. Mekanisme kedua parameter ini identik dengan pemanggilan fungsi Python biasa, sebagaimana ditunjukkan potongan berikut.
def hitung_rata_rata(nilai):
return sum(nilai) / len(nilai)
print(hitung_rata_rata(*[[70, 80, 90]]))
print(hitung_rata_rata(**{"nilai": [70, 80, 90]}))80.0
80.0Tanda bintang tunggal membongkar list menjadi argumen posisi, sedangkan tanda bintang ganda membongkar kamus menjadi argumen kata kunci. Operator melakukan hal yang sama saat task dieksekusi. Karena nilai merupakan satu argumen berupa list, bentuk op_args yang setara adalah op_args=[[70, 80, 90]], yaitu list yang berisi satu argumen tersebut. Fungsi dipanggil di dalam proses task, bukan saat berkas DAG diparse, sehingga logikanya tetap tertunda sampai task berjalan. Nilai kembalian fungsi tidak hilang begitu saja karena PythonOperator menyimpannya sebagai XCom, yakni mekanisme penyimpanan nilai agar dapat diambil oleh task lain.
Menyusun dan menjalankan DAG klasik#
Berkas dag_klasik.py berikut menggabungkan kedua operator dalam satu DAG dengan dua task. Task pertama mencetak pesan persiapan melalui BashOperator dengan bantuan variabel lingkungan, dan task kedua menghitung rata-rata deret nilai melalui PythonOperator dengan argumen kata kunci.
from airflow.providers.standard.operators.bash import BashOperator
from airflow.providers.standard.operators.python import PythonOperator
from airflow.sdk import dag
def hitung_rata_rata(nilai: list[int]) -> float:
"""Menghitung rata-rata dari deret nilai yang diterima."""
hasil = sum(nilai) / len(nilai)
print(f"Rata-rata: {hasil}")
return hasil
@dag(
dag_id="dag_klasik",
schedule=None,
description="Dua task gaya klasik: operator Bash dan operator Python.",
)
def dag_klasik():
persiapan = BashOperator(
task_id="persiapan",
bash_command="echo Menyiapkan data nilai ujian untuk $KOTA",
env={"KOTA": "Bandung"},
)
hitung = PythonOperator(
task_id="hitung_rata_rata",
python_callable=hitung_rata_rata,
op_kwargs={"nilai": [70, 80, 90]},
)
# task hitung_rata_rata baru berjalan setelah task persiapan selesai
persiapan >> hitung
dag_klasik()Baris persiapan >> hitung menyatakan dependensi antar task, yaitu task hitung_rata_rata baru berjalan setelah task persiapan selesai. Pada task persiapan, teks $KOTA di dalam bash_command mengambil nilai dari kamus env, sedangkan pada task hitung_rata_rata, kamus op_kwargs diteruskan kepada fungsi sebagai argumen kata kunci.
Berkas ini disalin ke folder dags pada lingkungan latihan terpisah sebelum dijalankan.
# lingkungan latihan terpisah untuk DAG klasik
export AIRFLOW_HOME=/tmp/ra-operator-bash-dan-python
# contoh DAG bawaan dimatikan agar pemrosesan folder dags cepat
export AIRFLOW__CORE__LOAD_EXAMPLES=False# uji bahwa berkas DAG dapat diparse tanpa keluaran apa pun
python3 dag_klasik.py# salin berkas DAG ke folder yang dipindai Airflow
mkdir -p "$AIRFLOW_HOME/dags"
cp dag_klasik.py "$AIRFLOW_HOME/dags/"# siapkan skema basis data metadata
# log migrasi berisi stempel waktu, sehingga tidak ditampilkan
airflow db migrate > /dev/null 2>&1Struktur DAG yang telah dibangun dapat diperiksa sekali lagi, kali ini sekaligus menampilkan kelas operator tiap task dan hubungan dependensinya.
# cetak kelas operator tiap task beserta task turunan dari persiapan
python3 -c "import dag_klasik; d = dag_klasik.dag_klasik(); print({t.task_id: type(t).__name__ for t in d.tasks}); print(sorted(d.get_task('persiapan').downstream_task_ids))"{'persiapan': 'BashOperator', 'hitung_rata_rata': 'PythonOperator'}
['hitung_rata_rata']Keluaran memperlihatkan dua task dengan kelas operatornya masing-masing, dan downstream_task_ids milik task persiapan berisi hitung_rata_rata sesuai notasi panah pada berkas dag_klasik.py. Setelah struktur sesuai harapan, seluruh DAG dijalankan sekali dengan dags test.
# jalankan seluruh task DAG klasik sekali secara lokal
# log panjang dan bertanda waktu, sehingga diarahkan ke berkas
airflow dags test dag_klasik 2026-11-04 > "$AIRFLOW_HOME/dags-test.log" 2>&1Keluaran perintahnya panjang dan bertanda waktu, sehingga diarahkan ke berkas. Pada akhir log, kedua task berstatus success dan dag run ditutup dengan status yang sama. Baris penting pada log kedua task diambil dengan pola pencarian.
Log task persiapan memuat baris Menyiapkan data nilai ujian untuk Bandung, yang membuktikan variabel lingkungan dari env benar-benar terbaca oleh perintah shell. Log task hitung_rata_rata memuat baris Rata-rata: 80.0 sesuai perhitungan atas deret 70, 80, dan 90. Nilai 80.0 itu juga tersimpan sebagai XCom hasil fungsi, dan pelacakannya dapat dilakukan pada tab XCom di UI.
# ambil baris bukti dari log kedua task
export AIRFLOW_HOME=/tmp/ra-operator-bash-dan-python
grep -o "Menyiapkan data nilai ujian untuk Bandung" "$AIRFLOW_HOME/dags-test.log"
grep -o "Rata-rata: 80.0" "$AIRFLOW_HOME/dags-test.log"Menyiapkan data nilai ujian untuk Bandung
Rata-rata: 80.0Perbedaan dengan TaskFlow API#
Gaya klasik memisahkan definisi fungsi dan pembuatan task, sedangkan TaskFlow API menyatukannya lewat decorator. Pada gaya klasik, pengoperan nilai antar task ditulis eksplisit melalui op_args atau op_kwargs dan hasilnya diambil dari XCom, sedangkan TaskFlow API menyambungkan nilai kembalian ke argumen task berikutnya secara otomatis. Gaya klasik tetap dipertahankan Airflow karena banyak operator pihak ketiga dan contoh lama masih menggunakannya, sehingga kemampuan membaca kedua gaya sama pentingnya dengan kemampuan menulis gaya TaskFlow.
Kesalahan umum#
- Menulis
python_callable=hitung_rata_rata()dengan tanda kurung. Fungsi langsung terpanggil saat berkas DAG diparse, sehingga parameter tersebut menerima nilai kembalian fungsi, bukan fungsinya, dan berkas gagal diparse dengan pesan bahwapython_callableharus berupa callable. Perbaikannya dengan meneruskan nama fungsi tanpa tanda kurung dan mengirim argumennya melaluiop_argsatauop_kwargs. - Menaruh logika berat pada level modul berkas DAG. Kode pada level modul dijalankan ulang setiap kali berkas diparse, sehingga pekerjaan yang seharusnya milik task ikut berulang. Perbaikannya dengan memindahkan logika ke dalam fungsi yang dirujuk
python_callable.
Ringkasan#
- BashOperator menjalankan
bash_commandmelalui shell dan menyalin exit code perintah menjadi status task. - Parameter
envmemberi variabel lingkungan khusus pada perintah, sedangkanappend_env=Truemembuat lingkungan proses Airflow ikut diwarisi. - PythonOperator memanggil
python_callabledari level modul berkas DAG dengan argumenop_argsatauop_kwargs, lalu menyimpan nilai kembaliannya sebagai XCom. - Notasi
>>menghubungkan dua task sehingga task hilir berjalan setelah task hulurnya selesai, danairflow dags testmemverifikasi seluruh task secara lokal beserta lognya.
Referensi#
- BashOperator — Apache Airflow
— Dokumentasi parameter BashOperator termasuk
bash_command,env, danappend_env. - PythonOperator — Apache Airflow
— Dokumentasi parameter PythonOperator termasuk
python_callable,op_args, danop_kwargs. - Best Practices — Apache Airflow — Praktik penulisan DAG, termasuk soal kode pada level modul berkas DAG.