Python ile komut satırı aracı yazmanın standart yolu argparse modülüdür: programın hangi argümanları beklediğini ArgumentParser nesnesine tanımlarsınız, modül sys.argv listesini sizin yerinize ayrıştırır, değerleri doğru tipe çevirir, -h yardım metnini kendiliğinden üretir ve kullanıcı yanlış bir şey yazdığında anlaşılır bir hata mesajıyla çıkar. Ek paket kurmanız gerekmez; modül Python 3.2 sürümünden beri standart kütüphanededir.
Bu yazıda konumsal ve isteğe bağlı argümanları, action, nargs, type ve choices parametrelerini, alt komutları, karşılıklı dışlayan grupları ve hata yönetimini çalışan örneklerle anlatıyoruz. Python 3.15 ile gelen değişiklikler (yanlış yazılan seçenekler için varsayılan öneri, yardım metninde ters tırnak vurgusu, kısa ve tek tireli uzun seçenekte dest kuralı) ayrı bir bölümde. Tüm örnekler Python 3.15.2 ile çalıştırıldı.
sys.argv yerine neden argparse?
Komut satırına yazılan her şey Python'a sys.argv adında bir metin listesi olarak gelir. İlk eleman betiğin adıdır, geri kalanlar kullanıcının yazdıklarıdır. Küçük bir betikte sys.argv[1] okumak yeterli görünebilir; ancak seçeneklerin sırası değiştiğinde, bir değer eksik kaldığında, sayı beklenen yere metin yazıldığında ya da kullanıcı yardım istediğinde bu kontrollerin hepsini elle yazmanız gerekir. argparse bu işlerin tamamını tanımladığınız kurallardan türetir: neyin zorunlu olduğunu, hangi tipe çevrileceğini ve yardım ekranında nasıl görüneceğini tek yerde belirtirsiniz.
Modülün üç temel parçası vardır. ArgumentParser program düzeyindeki ayarları (program adı, açıklama, alt metin) tutar. add_argument() her bir argümanın kuralını ekler. parse_args() ise ayrıştırmayı çalıştırır ve sonucu Namespace adlı basit bir nesnede, öznitelik olarak döndürür. Python belgeleri daha karmaşık gereksinimler için (örneğin seçeneklerle konumsal argümanların karışmasını tamamen kapatmak) başka kütüphanelere bakılabileceğini de not eder; sıradan araçların büyük çoğunluğu için argparse yeterlidir.
İlk komut satırı aracınız
Aşağıdaki selam.py betiği bir konumsal argüman (isim), değer alan bir seçenek (-t/--tekrar) ve açma kapama bayrağı (-b/--buyuk) tanımlar. Yardım metnindeki %(default)s belirteci, varsayılan değeri yardım ekranına otomatik yazar.
import argparse
parser = argparse.ArgumentParser(
prog='selam',
description='Verilen isme selam verir.')
parser.add_argument('isim') # konumsal argüman
parser.add_argument('-t', '--tekrar', type=int, default=1,
help='kaç kez yazılacağı (varsayılan: %(default)s)')
parser.add_argument('-b', '--buyuk', action='store_true',
help='çıktıyı büyük harfle yaz')
args = parser.parse_args()
print(args)
metin = f'Merhaba {args.isim}!'
if args.buyuk:
metin = metin.upper()
for _ in range(args.tekrar):
print(metin)Betiği farklı argümanlarla çalıştırdığımızda gördüğümüz gerçek çıktılar şunlar:
$ python selam.py Ayşe -t 2 --buyuk
Namespace(isim='Ayşe', tekrar=2, buyuk=True)
MERHABA AYŞE!
MERHABA AYŞE!
$ python selam.py --help
usage: selam [-h] [-t TEKRAR] [-b] isim
Verilen isme selam verir.
positional arguments:
isim
options:
-h, --help show this help message and exit
-t, --tekrar TEKRAR kaç kez yazılacağı (varsayılan: 1)
-b, --buyuk çıktıyı büyük harfle yazDikkat edilecek birkaç nokta var. -t 2 değeri komut satırından metin olarak gelir, type=int sayesinde Namespace içinde tam sayı olur. --tekrar seçeneğinin değeri args.tekrar adıyla okunur; uzun seçenek adındaki tireler alt çizgiye çevrilir (--dosya-adi için args.dosya_adi). Yardım ekranındaki TEKRAR yazısı metavar olarak adlandırılır ve varsayılan olarak hedef adın büyük harfli hâlidir. -h/--help seçeneğini siz eklemediniz; add_help=True varsayılanı onu her parser'a ekler.
Yanlış kullanımda modül, kullanım satırını ve hatayı standart hata akışına yazar ve programı 2 çıkış koduyla sonlandırır:
$ python selam.py
usage: selam [-h] [-t TEKRAR] [-b] isim
selam: error: the following arguments are required: isim
$ python selam.py Ali -t iki
usage: selam [-h] [-t TEKRAR] [-b] isim
selam: error: argument -t/--tekrar: invalid int value: 'iki'Konumsal ve isteğe bağlı argümanlar
add_argument() çağrısına verdiğiniz ilk metin, argümanın türünü belirler. Tire ile başlamayan bir ad ('isim') konumsal argümandır: kullanıcı onu yazmak zorundadır ve sırası önemlidir. -t ya da --tekrar gibi tireli adlar isteğe bağlı seçeneklerdir; yazılmazsa değeri default olur, o da verilmemişse None. Bir seçeneğe hem kısa hem uzun ad verebilirsiniz; hedef öznitelik adı uzun adla belirlenir.
Değer alan seçeneklerde birkaç yazım biçimi geçerlidir: --tekrar 3, --tekrar=3, kısa seçenekte bitişik -t3. Değer almayan kısa bayraklar tek tire altında birleştirilebilir; -xyz yazımı, son harf hariç hepsi değer almıyorsa -x -y -z anlamına gelir. Uzun seçenekler, belirsizlik yoksa kısaltılarak da yazılabilir (--tek yazımı --tekrar olarak anlaşılır). Bu davranış istenmiyorsa allow_abbrev=False verin.
Seçenekleri zorunlu yapmak için required=True kullanılabilir; ancak belgeler kullanıcıların "seçenek" kelimesinden isteğe bağlılık beklediğini hatırlatır ve bunun mümkünse kaçınılması gereken bir tasarım olduğunu söyler. Zorunlu bir bilgi için konumsal argüman genellikle daha doğal bir seçimdir.
add_argument parametreleri

Bir argümanın davranışı add_argument() anahtar kelimeleriyle belirlenir. Aşağıdaki tablo en sık kullanılanları özetler:
| Parametre | Ne işe yarar | Örnek |
|---|---|---|
| action | Argüman görüldüğünde ne yapılacağı (varsayılan store) | action='store_true' |
| nargs | Kaç değer tüketileceği: sayı, ?, *, + | nargs='+' |
| type | Metni dönüştüren çağrılabilir nesne | type=int, type=pathlib.Path |
| default | Argüman yoksa kullanılacak değer | default=1 |
| choices | İzin verilen değerler listesi | choices=['gzip', 'yok'] |
| required | Seçeneği zorunlu yapar (yalnızca seçenekler) | required=True |
| help | Yardım ekranındaki açıklama | help='çıktı dosyası' |
| metavar | Yardımda görünen değer adı | metavar='DOSYA' |
| dest | Namespace içindeki öznitelik adı | dest='cikti' |
| deprecated | Kullanılınca uyarı yazdırır (3.13 ile geldi) | deprecated=True |
nargs değerlerinin anlamı şöyledir: tam sayı N tam N değeri bir liste olarak toplar (nargs=1 bile tek elemanlı liste üretir); '?' bir değeri varsa alır, yoksa default kullanır (seçenek yazılıp değer verilmezse const devreye girer); '*' sıfır ya da daha fazla değeri listeye toplar; '+' en az bir değer ister, hiç yoksa hata verir. nargs verilmezse tek değer okunur ve liste değil, değerin kendisi saklanır.
action türleri ve çoklu değerler

Varsayılan store eylemi değeri olduğu gibi saklar. Diğer yerleşik eylemler farklı ihtiyaçlara karşılık gelir: store_true ve store_false bayrak içindir; count seçeneğin kaç kez yazıldığını sayar (-vvv gibi ayrıntı seviyeleri için); append aynı seçeneğin her kullanımını bir listeye ekler; extend çok değerli bir seçeneğin değerlerini tek listeye yayar; version sürüm bilgisini yazıp çıkar.
import argparse
p = argparse.ArgumentParser(prog='yedek')
p.add_argument('dosyalar', nargs='+')
p.add_argument('-v', '--verbose', action='count', default=0)
p.add_argument('--etiket', action='append', default=[])
p.add_argument('--sikistir', choices=['gzip', 'bz2', 'yok'], default='yok')
print(p.parse_args(['a.txt', 'b.txt', '-vv', '--etiket', 'gunluk', '--etiket', 'acil']))
# çıktı: Namespace(dosyalar=['a.txt', 'b.txt'], verbose=2, etiket=['gunluk', 'acil'], sikistir='yok')
print(p.parse_args(['c.txt', '--sikistir=gzip']))
# çıktı: Namespace(dosyalar=['c.txt'], verbose=0, etiket=[], sikistir='gzip')
print(vars(p.parse_args(['d.txt'])))
# çıktı: {'dosyalar': ['d.txt'], 'verbose': 0, 'etiket': [], 'sikistir': 'yok'}Bu örnekte parse_args() fonksiyonuna liste verdik. Liste verilmezse sys.argv[1:] kullanılır; liste vermek, aracı test ederken ve bu yazıdaki gibi denemeler yaparken çok işe yarar. vars() yerleşik fonksiyonu Namespace nesnesini sözlüğe çevirir; sonucu JSON'a yazmak ya da başka bir fonksiyona ** ile açmak istediğinizde kullanışlıdır.
type ile dönüştürme ve doğrulama
type parametresi tek bir metin alan herhangi bir çağrılabilir nesne olabilir: int, float, pathlib.Path ya da kendi fonksiyonunuz. Fonksiyon ArgumentTypeError, TypeError veya ValueError fırlatırsa argparse bunu yakalar ve düzgün biçimlenmiş bir hata mesajına çevirir. Başka bir istisna türü yakalanmaz. Varsayılan değer bir metinse dönüştürme ona da uygulanır; metin değilse değer olduğu gibi kullanılır.
import argparse
p = argparse.ArgumentParser(prog='hesap', exit_on_error=False)
p.add_argument('--adet', type=int)
try:
p.parse_args(['--adet', 'beş'])
except argparse.ArgumentError as e:
print('Yakalandı:', e)
# çıktı: Yakalandı: argument --adet: invalid int value: 'beş'
def pozitif(metin):
sayi = int(metin)
if sayi <= 0:
raise argparse.ArgumentTypeError(f'{sayi} pozitif değil')
return sayi
q = argparse.ArgumentParser(prog='hesap')
q.add_argument('--adet', type=pozitif)
print(q.parse_args(['--adet', '4']))
# çıktı: Namespace(adet=4)
q.parse_args(['--adet', '-2'])
# usage: hesap [-h] [--adet ADET]
# hesap: error: argument --adet: -2 pozitif değilBurada iki ayrıntı öne çıkıyor. Birincisi exit_on_error=False: parser hata durumunda programı kapatmak yerine ArgumentError fırlatır, siz de yakalayıp kendi akışınızı sürdürürsünüz. İkincisi -2 değerinin seçenek sanılmamasıdır. Parser'da negatif sayıya benzeyen bir seçenek tanımlı olmadığı için -2 bir değer olarak kabul edildi. Tireyle başlayan ve sayıya benzemeyen bir değeri konumsal argüman olarak geçmek gerekiyorsa, önüne -- yazarak "bundan sonrası seçenek değil" diyebilirsiniz.
Belgelerin açıkça uyardığı bir tuzak type=bool kullanımıdır. bool() boş metni False, boş olmayan her metni True yapar; yani --hatali False yazmak True üretir. Açma kapama için store_true ya da hem --renk hem --no-renk biçimini tek tanımla üreten BooleanOptionalAction kullanın:
import argparse
p = argparse.ArgumentParser(prog='ayar')
p.add_argument('--renk', action=argparse.BooleanOptionalAction, default=True)
p.add_argument('--hatali', type=bool)
print(p.parse_args([]))
# çıktı: Namespace(renk=True, hatali=None)
print(p.parse_args(['--no-renk']))
# çıktı: Namespace(renk=False, hatali=None)
print(p.parse_args(['--hatali', 'False']))
# çıktı: Namespace(renk=True, hatali=True)JSON ya da YAML çözümleme, dosya açma gibi karmaşık hata durumları olan dönüşümleri type içinde yapmamak gerekir; belgeler bunları ayrıştırmadan sonra, uygulama kodunda ele almayı önerir. Aynı nedenle argparse.FileType Python 3.14 itibarıyla kullanımdan kaldırılmak üzere işaretlendi (deprecated): bir argüman dosyayı açtıktan sonra sonraki argüman hata verirse dosya kapatılmadan kalabiliyordu. Dosya yolunu type=pathlib.Path ile alıp dosyayı with bloğunda açmak daha güvenlidir.
choices ve Python 3.15 ile gelen öneriler
Bir argüman yalnızca belirli değerleri alabiliyorsa choices listesi verin. Değerler, type dönüşümü yapıldıktan sonra kontrol edilir; yani type=int ile birlikte choices sayılardan oluşmalıdır. Python 3.15 ile suggest_on_error parametresinin varsayılanı True oldu: kullanıcı geçerli bir seçeneğe yakın bir değer yazdığında hata mesajı "maybe you meant" önerisi içerir. Bu özellik yalnızca seçenekleri metin olan choices listelerinde ve alt komut adlarında çalışır.
import argparse
p = argparse.ArgumentParser(prog='derle')
p.add_argument('--mod', choices=['debug', 'release'])
p.parse_args(['--mod', 'relase'])
# usage: derle [-h] [--mod {debug,release}]
# derle: error: argument --mod: invalid choice: 'relase', maybe you meant 'release'? (choose from 'debug', 'release')Belgeler choices için enum.Enum kullanılmasını önermez; çünkü yardım, kullanım ve hata metinlerinde nasıl görüneceğini denetlemek zorlaşır. Çok sayıda seçenek yardım ekranını kalabalıklaştırıyorsa açık bir metavar verebilirsiniz.
Alt komutlar: git benzeri araçlar
git commit, git push gibi her biri farklı argüman alan komutlar için add_subparsers() kullanılır. Bu çağrı özel bir eylem nesnesi döndürür; onun add_parser() metodu her alt komut için ayrı bir ArgumentParser üretir. Belgelerin önerdiği etkili desen, her alt parser'a set_defaults(func=...) ile çalıştıracağı fonksiyonu bağlamaktır. Böylece ayrıştırmadan sonra args.func(args) demek yeterli olur.
import argparse
def ekle(args):
print(f'{args.ad} eklendi (öncelik {args.oncelik})')
def listele(args):
print('Görevler listeleniyor, tamamlananlar:', args.hepsi)
parser = argparse.ArgumentParser(prog='gorev')
alt = parser.add_subparsers(dest='komut', required=True)
p_ekle = alt.add_parser('ekle', help='yeni görev ekler')
p_ekle.add_argument('ad')
p_ekle.add_argument('-o', '--oncelik', type=int, default=3)
p_ekle.set_defaults(func=ekle)
p_liste = alt.add_parser('liste', aliases=['ls'], help='görevleri listeler')
p_liste.add_argument('--hepsi', action='store_true')
p_liste.set_defaults(func=listele)
for satir in (['ekle', 'Fatura öde', '-o', '1'], ['ls', '--hepsi']):
args = parser.parse_args(satir)
print(args.komut, end=': ')
args.func(args)
# çıktı: ekle: Fatura öde eklendi (öncelik 1)
# çıktı: ls: Görevler listeleniyor, tamamlananlar: Truedest='komut' seçilen alt komutun adını saklar; takma ad kullanıldığında (ls) yazılan ad kaydedilir. required=True verilmezse kullanıcı hiç alt komut yazmadan da program çalışır ve args.func bulunmadığı için hata alırsınız. Dönen Namespace yalnızca ana parser'ın ve seçilen alt parser'ın özniteliklerini içerir; diğer alt komutların argümanları görünmez. Bir alt parser, ana parser ile aynı dest adını kullanırsa ikisi tek özniteliği paylaşır ve ana değer korunmaz; farklı adlar verin.
Karşılıklı dışlayan seçenekler
--sessiz ve --ayrintili gibi birlikte kullanılması anlamsız seçenekleri add_mutually_exclusive_group() ile gruplayabilirsiniz. Grup required=True alırsa kullanıcının en az birini seçmesi gerekir.
import argparse
p = argparse.ArgumentParser(prog='cikti')
grup = p.add_mutually_exclusive_group()
grup.add_argument('-q', '--sessiz', action='store_true')
grup.add_argument('-v', '--ayrintili', action='store_true')
print(p.parse_args(['-q']))
# çıktı: Namespace(sessiz=True, ayrintili=False)
p.parse_args(['-q', '-v'])
# usage: cikti [-h] [-q | -v]
# cikti: error: argument -v/--ayrintili: not allowed with argument -q/--sessizYardım ekranında seçenekleri başlık altında toplamak için ise add_argument_group() vardır; bu yalnızca görünümü düzenler, kural koymaz. Python 3.14 ile dışlayan bir grubun içinde yeniden grup açmak hata fırlatır hâle geldi; bu iç içe kullanım hiçbir zaman desteklenmiyordu.
Bilinmeyen argümanları başka araca bırakmak
Bazen betiğiniz yalnızca kendi seçeneklerini okuyup kalanını başka bir programa aktarmalıdır. parse_known_args() tanımadığı argümanlar için hata vermez; bir (Namespace, kalan_liste) ikilisi döndürür. Önek eşleştirmesi bu metotta da geçerlidir; kısaltma gibi görünen bir argüman tanınan seçeneğe bağlanabilir.
import argparse
p = argparse.ArgumentParser(prog='calistir')
p.add_argument('--debug', action='store_true')
args, kalan = p.parse_known_args(['--debug', '--port', '8080', 'app.py'])
print(args)
# çıktı: Namespace(debug=True)
print(kalan)
# çıktı: ['--port', '8080', 'app.py']Python 3.15 ile argparse'ta neler değişti?

3.15 sürüm notlarında argparse için şu maddeler yer alıyor:
suggest_on_errorvarsayılanıTrueoldu; yanlış yazılan seçim ve alt komut adları için öneri artık kendiliğinden geliyor (parametre 3.14 ile eklenmişti).BooleanOptionalActiontek tireli uzun seçenekleri (-fooiçin-nofoo) ve farklı önek karakterlerini destekliyor.- Açıklama, alt metin ve argüman
helpmetinlerinde tek ya da çift ters tırnak arasına yazılan kod parçaları, renk açıkken farklı renkte gösteriliyor; renk kapalıyken tırnaklar olduğu gibi kalıyor. add_argument('-f', '-foo')gibi kısa seçenekle tek tireli uzun seçenek birlikte verildiğindedestartık uzun addan çıkarılıyor. Eski davranışı korumak içindestdeğerini açıkça yazın.- Modülün
__version__özniteliği kullanımdan kaldırılmak üzere işaretlendi; 3.20 sürümünde silinmesi planlanıyor.
import argparse
p = argparse.ArgumentParser(prog='eski')
p.add_argument('-f', '-foo')
print(p.parse_args(['-f', '1']))
# çıktı: Namespace(foo='1')
q = argparse.ArgumentParser(prog='eski')
q.add_argument('-f', '-foo', dest='f')
print(q.parse_args(['-f', '1']))
# çıktı: Namespace(f='1')Sürümün diğer yenilikleri için Python 3.15 yenilikleri yazısına bakabilirsiniz.
Sık yapılan hatalar
- Tip dönüştürmeyi unutmak:
typeverilmeyen her değer metindir;args.port + 1gibi işlemlerTypeErrorverir. type=boolkullanmak: her boş olmayan metinTrueolur.store_trueya daBooleanOptionalActionkullanın.- Yardım metninde tek
%yazmak: help metni %-biçimlendirmeden geçer; yüzde işareti için%%yazın. - Alt komutta
required=Truevermemek: komutsuz çağrıdaargs.funcbulunamaz. - Ayrıştırmayı modül yüklenirken yapmak:
parse_args()çağrısınıif __name__ == '__main__':bloğuna ya da birmain()fonksiyonuna koyun; aksi hâlde modülü başka yerden içe aktarmak da argüman okumaya çalışır. Konu için modül ve paket yazısına bakın. - Çıkış kodunu yok saymak: ayrıştırma hatası 2 koduyla çıkar; kabuk betikleri ve cron görevleri bu kodu kontrol edebilir.
Sık Sorulan Sorular
argparse ile optparse arasındaki fark nedir?
Taşıma rehberine göre argparse, optparse modülünün kendi başına sunmadığı konumsal argüman işleme, alt komutlar, sıfır veya daha fazla değer alan argümanlar ve daha bilgilendirici kullanım mesajları gibi özellikler sağlar. Belgeler temel komut satırı uygulamaları için argparse modülünü önerir; ancak optparse ile çalışan ve bundan memnun olan uygulamaların taşınmak zorunda olmadığını, seçeneklerle konumsal argümanların karışmasını daha ince denetlemek gibi durumlarda optparse modülünün hâlâ bir alternatif olduğunu da belirtir.
Argümanları test ederken komut satırına mı yazmam gerekir?
Hayır. parser.parse_args(['--adet', '4']) gibi bir liste verdiğinizde sys.argv hiç okunmaz. Bu yöntem birim testlerde de kullanılır; unittest ile test yazma yazısında testlerin nasıl kurulacağını anlattık.
Hata olduğunda programın kapanmasını nasıl engellerim?
ArgumentParser(exit_on_error=False) ile oluşturun ve argparse.ArgumentError istisnasını yakalayın. Hata yakalama mantığının ayrıntıları için try/except rehberine bakabilirsiniz.
Ayrıntı seviyesini -v, -vv, -vvv ile nasıl yaparım?
add_argument('-v', action='count', default=0) tanımlayın. default verilmezse seçenek yazılmadığında değer None olur; karşılaştırma yaparken hata almamak için 0 vermek iyi bir alışkanlıktır. Bu sayıyı logging seviyelerine bağlamak yaygın bir yöntemdir.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Python öğrenme rehberi · unittest ile test yazma · Modül ve paket import · logging modülü · Python 3.15 yenilikleri