argparse

Membangun CLI dengan argparse, meliputi flag, teks bantuan, dan subcommand.

Daftar isi

Modul argparse membangun antarmuka baris perintah (command line interface, CLI) yang membaca argumen, memvalidasinya, dan menyusun teks bantuannya secara otomatis. Membaca sys.argv secara langsung menuntut penguraian manual dan penanganan kesalahan sendiri, sedangkan argparse mendeklarasikan argumen yang diharapkan sekali di awal, lalu mengurus sisanya. Topik ini membahas argumen posisi dan opsi (flag), teks bantuan otomatis, penolakan nilai yang tidak valid, pengujian parser, serta subcommand untuk program berbanyak mode.

Argumen posisi dan opsi#

Argumen posisi wajib diisi dan dibaca menurut urutannya, sedangkan opsi berawalan dua tanda hubung dan bersifat pilihan. Metode add_argument() mendeklarasikan keduanya, dengan action="store_true" untuk opsi tipe bendera (flag) yang cukup muncul tanpa nilai, dan type= untuk mengonversi teks menjadi tipe tertentu. Hasil penguraian terkumpul pada objek yang atributnya dinamai sesuai argumennya.

python sapa.py
# tidak-dijalankan: skrip CLI, dijalankan lewat perintah terminal pada blok berikutnya
import argparse

parser = argparse.ArgumentParser(description="Menyapa nama yang diberikan.")
parser.add_argument("nama", help="nama yang disapa")
parser.add_argument("--kapital", action="store_true", help="mencetak sapaan dalam huruf kapital")
parser.add_argument("--ulang", type=int, default=1, help="jumlah pengulangan sapaan")
args = parser.parse_args()

sapaan = f"Halo, {args.nama}!"
if args.kapital:
    sapaan = sapaan.upper()
for _ in range(args.ulang):
    print(sapaan)

Apabila skrip dijalankan tanpa satu pun argumen, argparse menolaknya dan menjelaskan apa yang kurang.

bash
# menjalankan sapa.py tanpa argumen
python3 sapa.py
text Keluaran
usage: sapa.py [-h] [--kapital] [--ulang ULANG] nama
sapa.py: error: the following arguments are required: nama

Pesan errornya menyebut pola pemakaian yang benar beserta argumen yang belum diisi, dan penolakan ini terjadi tanpa satu baris pemeriksaan pun ditulis. Berikut adalah pemanggilan yang lengkap dengan keduanya, yaitu opsi tipe bendera dan opsi bernilai.

bash
# menjalankan sapa.py dengan opsi kapital dan ulang
python3 sapa.py Ali --kapital --ulang 2
text Keluaran
HALO, ALI!
HALO, ALI!

Opsi --kapital bernilai True karena muncul, sedangkan --ulang menerima bilangan 2 yang dikonversi dengan type=int sebelum digunakan. Apabila --ulang tidak dikirim, atributnya bernilai sesuai default yang dideklarasikan, yaitu 1, sehingga nilai cadangan menjadi bagian dari deklarasi dan bukan logika tambahan.

Teks bantuan otomatis#

Setiap parser dan setiap argumen secara otomatis mendukung opsi -h dan --help. Teks bantuan menyusun ringkasan pemakaian, deskripsi program, daftar argumen posisi, dan daftar opsi beserta maknanya, seluruhnya dari parameter description dan help yang telah dideklarasikan. Contoh berikut mengunci lebar teks pada 80 kolom melalui variabel COLUMNS agar pemenggalan barisnya tetap, karena argparse menyesuaikan pemenggalan dengan lebar terminal.

bash
# menampilkan teks bantuan otomatis
COLUMNS=80 python3 sapa.py --help
text Keluaran
usage: sapa.py [-h] [--kapital] [--ulang ULANG] nama

Menyapa nama yang diberikan.

positional arguments:
  nama           nama yang disapa

options:
  -h, --help     show this help message and exit
  --kapital      mencetak sapaan dalam huruf kapital
  --ulang ULANG  jumlah pengulangan sapaan

Baris pertama menunjukkan pola pemakaian lengkap, dan dua daftar berikutnya menjelaskan setiap argumen dengan teks help masing-masing. Bantuan semacam ini biasanya menjadi bagian yang paling sering ditunda karena merepotkan, padahal argparse menyusunnya tanpa biaya tambahan selama deklarasi argumen menyertakan teks penjelasnya. Dokumentasi CLI yang selalu mutakhir adalah konsekuensi langsung dari kebiasaan mengisi help.

Penolakan nilai yang tidak valid#

Parameter type bukan sekadar konversi, tetapi juga lapis validasi. Apabila nilai yang dikirim tidak dapat dikonversi, argparse menghentikan program dengan pesan yang menyebut opsi dan nilai yang ditolaknya, tanpa membiarkan nilai salah masuk ke logika utama.

bash
# memberi nilai yang bukan bilangan bulat pada --ulang
COLUMNS=80 python3 sapa.py Ali --ulang banyak
text Keluaran
usage: sapa.py [-h] [--kapital] [--ulang ULANG] nama
sapa.py: error: argument --ulang: invalid int value: 'banyak'

Pesan invalid int value muncul karena banyak gagal dikonversi menjadi bilangan bulat, dan program berhenti dengan kode keluar 2 yang menjadi tanda kesalahan pemakaian CLI. Pemilihan kata pada pesan diatur oleh deklarasi, misalnya choices=["merah", "biru"] menyebabkan nilai di luar daftar ditolak dengan pesan serupa. Dengan demikian, validasi bentuk argumen selesai di lapis parser, dan logika utama cukup memikirkan isi programnya.

Parser yang sama juga dapat diuji tanpa terminal karena metode parse_args() menerima daftar argumen eksplisit. Metode itu hanya membaca sys.argv ketika dipanggil tanpa argumen.

python Contoh: menguji parser dengan daftar argumen
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("angka", type=int)
args = parser.parse_args(["5"])
print(args.angka * 3)
text Keluaran
15

Pola ini memungkinkan logika penguraian diuji dari REPL atau dari pengujian otomatis tanpa menjalankan proses baru. Konstruksi parser yang terpisah dari logika program pun menjadi kebiasaan yang memudahkan pengujian semacam ini.

Subcommand#

Program yang menyediakan beberapa mode kerja, misalnya git dengan commit dan push, memetakan pola tersebut melalui subcommand. Metode add_subparsers() mengaktifkan dukungan subcommand pada parser, dan setiap subparser memiliki argumennya sendiri. Parser utama tetap dapat menampung opsi umum, dengan catatan opsi milik parser utama ditempatkan sebelum nama subcommand.

python catatan.py
# tidak-dijalankan: skrip CLI, dijalankan lewat perintah terminal pada blok berikutnya
import argparse

parser = argparse.ArgumentParser(description="Pengelola catatan sederhana di terminal.")
parser.add_argument("--verbose", action="store_true", help="menampilkan pesan proses")

sub = parser.add_subparsers(dest="perintah", required=True)

tambah = sub.add_parser("tambah", help="menambahkan catatan baru")
tambah.add_argument("teks", help="isi catatan yang disimpan")

daftar = sub.add_parser("daftar", help="menampilkan seluruh catatan")
daftar.add_argument("--nomor", action="store_true", help="menomori daftar catatan")

args = parser.parse_args()

catatan = ["belajar argparse", "menulis laporan mingguan", "rapat pukul 10"]

if args.perintah == "tambah":
    catatan.append(args.teks)
    if args.verbose:
        print("menyimpan catatan baru")
    print("total catatan:", len(catatan))
elif args.perintah == "daftar":
    for nomor, isi in enumerate(catatan, start=1):
        print(f"{nomor}. {isi}" if args.nomor else isi)

Parameter dest="perintah" menyimpan nama subcommand yang dipilih pada atribut args.perintah, sedangkan required=True menyebabkan pemanggilan tanpa subcommand ditolak dengan pesan error.

bash
# menampilkan catatan tanpa penomoran
python3 catatan.py daftar
text Keluaran
belajar argparse
menulis laporan mingguan
rapat pukul 10

Opsi milik subparser hanya berlaku pada subcommandnya, sehingga --nomor diterima pada daftar dan ditolak pada tambah.

bash
# menampilkan catatan dengan penomoran
python3 catatan.py daftar --nomor
text Keluaran
1. belajar argparse
2. menulis laporan mingguan
3. rapat pukul 10

Opsi --verbose milik parser utama ditempatkan sebelum kata tambah, karena setelah subcommand terpilih, penguraian beralih ke subparser yang tidak mengenal opsi tersebut.

bash
# opsi parser utama berada sebelum nama subcommand
python3 catatan.py --verbose tambah "belajar subcommand"
text Keluaran
menyimpan catatan baru
total catatan: 4

Dengan struktur ini, program membaca args.perintah lalu bercabang ke tiap mode, dan setiap mode bekerja dengan argumennya sendiri. Untuk program yang mode kerjanya bertambah dari waktu ke waktu, struktur ini lebih mudah dirawat daripada satu tumpukan opsi dengan arti yang berubah-ubah.

Kesalahan umum#

Kesalahan pertama adalah lupa memanggil parse_args(). Variabel args yang berisi objek parser langsung diakses atributnya, sehingga error yang muncul tidak langsung menunjuk penyebabnya.

python Contoh: lupa memanggil parse_args
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("nama")

args = parser  # keliru, seharusnya parser.parse_args()
try:
    print(args.nama)
except AttributeError as e:
    print("AttributeError:", e)
text Keluaran
AttributeError: 'ArgumentParser' object has no attribute 'nama'

Objek parser memang tidak menyimpan hasil penguraian, dan nilai argumen hanya tersedia setelah parse_args() dijalankan. Kesalahan kedua adalah salah membaca nama atribut hasil opsi yang mengandung tanda hubung, karena tanda hubung otomatis menjadi garis bawah pada nama atribut Python.

python Contoh: tanda hubung menjadi garis bawah pada atribut
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--pilih-nomor", action="store_true")
args = parser.parse_args(["--pilih-nomor"])
print(args.pilih_nomor)
text Keluaran
True

Akses args.pilih-nomor justru dibaca sebagai operasi pengurangan, sehingga bentuk garis bawah adalah satu-satunya yang benar. Kesalahan ketiga adalah membaca angka tanpa type=, sehingga nilai yang diterima tetap string dan operasi aritmetikanya berubah makna.

python Contoh: angka dibaca sebagai string tanpa type
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("angka")
args = parser.parse_args(["5"])
print(args.angka, type(args.angka).__name__)
print(args.angka * 3)
text Keluaran
5 str
555

Perkalian string mengulang teksnya tiga kali alih-alih menghitung, dan deklarasi type=int pada bagian validasi menghasilkan 15 seperti yang diharapkan. Ketiga kesalahan ini tidak menimbulkan error saat penguraian, sehingga pengujian parser dengan parse_args(["..."]) menjadi cara cepat menemukannya.

Ringkasan#

  • argparse mendeklarasikan argumen posisi dan opsi sekali di awal, lalu mengurus penguraian, nilai default, dan penolakan pemanggilan yang tidak lengkap.
  • Teks bantuan -h dan --help tersusun otomatis dari description dan help, sedangkan type melakukan konversi sekaligus validasi dengan kode keluar 2 bila gagal.
  • parse_args() menerima daftar eksplisit untuk pengujian, dan membaca sys.argv bila dipanggil tanpa argumen.
  • add_subparsers() memetakan subcommand dengan argumen per mode, dan opsi parser utama ditempatkan sebelum nama subcommand.

Referensi#