Modul argparse je poslední inkarnací nadstavbových modulů pro zpracování argumentů příkazové řádky skriptu.
Názory na jeho uspořádání a použití se různí, ale za sebe mohu říct, že pro člověka, který potřebuje příležitostně zpracovat pár argumentů na příkazové řádce, je na použití zdaleka nejprůhlednější a nejpříjemnější. Proto jsem mu věnoval samostatnou kapitolu, ve které se pokusím to důležité z oficiální dokumentace převyprávět na menší ploše.
Ukažme si nejdříve chování kódu vybaveného modulem argparse při různých voláních skriptu z příkazové řádky. Daný skript pouze (přehledně) vypisuje, jaké argumenty na příkazové řádce obdržel:
Nevíme, jak program vůbec zavolat, tak to zkusíme bez parametrů:
Aha, takže přepínače nejsou povinné, ale jméno souboru ano. Tak ho zkusíme přidat (test.html):
Vida, přepínače mají nějaké výchozí hodnoty. Nebyla by k nim nějaká nápověda?
python3 argparse.mod.py -h
Tak to zkusme všechno najednou:
-c
jsme změnili stylopisový soubor (klíč cssfile) z výchozího style.css na stylopis.css a přepínačem -x
jsme změnili výchozí hodnotu klíče xhtml_flag z False
na True
. test.html je jméno souboru (určeného ke zpracování).
python3 argparse.mod.py --xhtml --cssfile=stylopis.css test.html
(znak =
tam sice není povinný, ale lépe se to s ním čte)
Aby se neřeklo, tak ještě obligátní dotaz na verzi programu :)
Nový objekt pro zpracování argumentů příkazové řádky založíme pomocí třídy ArgumentParser. Ta má hafo nepovinných parametrů, z nichž nejužitečnější jsou asi následující dva:
description
– text v nápovědě mezi vzorem příkazové řádky a popisem jednotlivých argumentů
epilog
– text úplně na konci nápovědy
O přidávání argumentů do parseru se stará metoda add_argument(). Ta má jediný povinný parametr (nebo skupinu parametrů) – řetězec (řetězce) zadávající jména argumentů. Přitom nepovinné parametry (tzv. přepínače) se od povinných (pozičních) liší přítomností znaménka „-“
(v základním nastavení) před svým jménem:
Zadané argumenty z příkazové řádky skončí ve výstupním objektu Namespace
přímo pod svými „dlouhými“ jmény:
=
nebo mezery:
--xhtml haf
a --xhtml=haf
.
test.py -x -y -z ⇔ test.py -xyz
Za „vytažení“ argumentů z příkazové řádky je zodpovědná metoda parseru parse_args()
.
sys.argv
, ale podle potřeby jí stačí přeposlat jako vstup seznam řetězců (tedy v principu stejný seznam jako vrátí sys.argv[1:]
).
Ta se pokusí podle předpisů z metod add_argument() získat odpovídající hodnoty, kterými naplní návratový objekt Namespace
, kde jsou přístupné pod klasickou tečkovou notací:
Zároveň se metoda parse_args() pokusí pohlídat většinu chyb, ke kterým může dojít, a v případě výskytu jakékoli z nich běh programu zastaví:
Poziční argument, který začíná na označovač přepínače (ve výchozím nastavení tedy znak -
), může pochopitelně v některých případech při načítání způsobit pěkné trable. Chcete-li zdůraznit, že od jistého místa v zadání dále se vyskytují již pouze poziční argumenty, použijte pseudorozdělovač --
:
Konkrétní chování argumentů předepisuje armáda nepovinných parametrů, které jsou však všechny užitečné a proto si je postupně probereme:
default
– výchozí hodnota pro nezadaný argument
required
– je daný argument vyžadován?
dest
– alternativní název pro uložení argumentu
type
– typ argumetu
choices
– množina možných hodnot argumentu
action
– operace k vykonání při zadání argumentu
nargs
– násobnost argumentu
const
– konstanta (vyžadována některými kombinacemi action a nargs)
help
– nápověda pro argument
metavar
– alternativní označení argumentu do nápovědy
Výchozí hodnotou pro nepovinné argumenty je None
. Chceme-li jinou výchozí hodnotu, použijeme parametr default:
Poznámka 1: Nepovinné argumenty jsou především všechny přepínače (není-li pomocí required řečeno jinak), ale patří mezi ně i poziční s možnou násobností 0 (tedy při nargs="?" a nargs="*").
Poznámka 2: Nebude-li nepovinný argument zadán, můžeme místo „probublání“ výchozí hodnoty též úplně zamezit jeho objevení ve výsledném objektu pomocí volby default=argparse.SUPPRESS
.
Potřebujeme-li si přítomnost nějakého přepínače vynutit, použijeme atribut required:
Pokud z nejrůznějších důvodů potřebujeme uložit zadaný přepínač pod jiným názvem než je jeho „dlouhá“ hodnota z metody add_argument(), použijeme parametr dest:
Modul argparse umí pohlídat typ zadávaných parametrů a provést příslušnou automatickou konverzi z výchozího řetězce:
Jelikož typem může být odkaz na libovolný callable-objekt, tedy např. funkci nebo metodu, jsou možnosti zadání vskutku veliké – projde kupříkladu i zadání typu type=open
.
Vyrobení alternativního typu je směšně jednoduché – stačí např. předat odkaz na funkci, jejímž jediným vstupem bude příslušný řetězec z příkazové řádky. A s ním si pak už můžete dělat, co chcete.
argparse.ArgumentTypeError
.
Kupříkladu zadání hexadecimálního čísla v intervalu 0x00
až 0xff
by mohla hlídat například takováto funkce:
Pokud má mít nějaký přepínač pouze jistou množinu povolených hodnot, přidejte parametr choices=VÝBĚR, kde VÝBĚRem může být jakýkoliv typ, který podporuje operátor in
, zde například seznam:
Stejně tak dobře můžete ale napsat klidně i toto:
Parametr action určuje, co bude provedeno s hodnotou příslušného argumentu na příkazové řádce. Má k dispozici následující hlavní standardní operace..
store
– uloží zadanou hodnotu (ve výchozím nastavení jako řetězec) pod daným jménem; toto je výchozí chování metody add_argument()
store_const
– je-li odpovídající přepínač přítomen, uloží hodnotu parametru const= na tomto argumentu
store_true
& store_false
– uloží boolovskou hodnotu True
nebo False
append
– přidá zadanou hodnotu do seznamu (využití u opakujících se argumentů)
append_const
– je-li odpovídající přepínač přítomen, přidá do seznamu hodnotu parametru const= na tomto argumentu
..plus jednu specializovanou:
version
– vypíše hodnotu parametru version=
na tomto argumentu
Navíc si můžete připsat další vlastní operace rozšířením objektu argparse.Action
, budete-li potřebovat.
Uložení zadané hodnoty pod příslušným jménem je výchozí chování parseru argumentů:
Pro přepínače je možné použít specifický způsob zadání hodnoty – je-li nastaveno action='store_const'
, signalizuje přítomnost přepínače na příkazové řádce, že pod dané jméno se má uložit hodnota odpovídajícího parametru const=
:
Tyto dvě akce představují speciální variantu store_const
, pouze pod příslušné jméno je uložena odpovídající pravdivostní hodnota:
Parametr action='append'
je velmi výhodný například v případě, kdy se příkazová řádka skládá z více nezávislých kusů a některé z přepínačů se navzájem nepřebíjí (metodou „poslední vítězí“), ale naopak skládají dohromady:
Parametr action='append_const'
se chová velmi podobně jako parametr append, jen místo zadané hodnoty se ukládá hodnota z parametru const=
. Obzvláště šikovné, pokud má více argumentů stejný cíl:
Při zadání příslušného přepínače vypíše hodnotu parametru version=
na tomto argumentu. V nejjednodušším případě jako prostý řetězec..
..ale můžete použít i hodnoty nadefinované jinde:
parser = ArgumentParser(prog='TestovaciProgram')
.
Obecně určuje počet argumentů příslušejících pod stejné jméno příslušná akce (tj. parametr action) a většinou to znamená právě jednu hodnotu (a ve výchozím nastavení jako řetězec). Potřebujete-li ale jiné chování, parametr nargs umožňuje určit násobnost (počet výskytů) příslušného argumentu (převážně – ale ne vždy – přepínače). Pro rozlišení používá standardní označení N?*+
, konkrétní chování však záleží na typu argumentu:
N
– uvedený počet (N) argumentů z příkazové řádky bude složen dohromady do seznamu
?
– je-li přítomna, je z příkazová řádky načtena jedna hodnota
*
– z příkazové řádky řádky jsou všechny odpovídající argumenty zahrnuty do jednoho seznamu
+
– stejně jako *
, ale narozdíl od ní je alespoň jeden argument vyžadován, jinak dojde k chybě
Složí uvedený počet (N) argumentů z příkazové řádky do seznamu:
Pozor – vytvoření seznamu se týká i jednoho argumentu!
Je-li na příkazové řádce přítomna, načte právě jednu hodnotu. Není-li, pak se chování liší podle typu parametru:
default
const
Typické použití u pozičních argumentů je například pro volitelné vstupní/výstupní soubory:
Načte z příkazové řádky všechny odpovídající argumenty a zahrne je do jednoho seznamu. Ale když nakombinujete dohromady poziční argumenty a přepínače, musíte si dát pozor na jejich počet i pořadí:
Parametr nargs='+' se chová z větší části stejně jako nargs='*', ale narozdíl od něj je alespoň jeden argument na vstupu vyžadován, jinak dojde k chybě:
Jak jsme viděli na příkladu akcí store_const
a append_const
, určuje parametr const
hodnotu, která bude uložena/přidána pod příslušné jméno:
Kromě toho pro přepínače s násobností ?
(tedy nulakrát nebo právě jednou) dodává výchozí hodnotu, nejsou-li uvedeny:
Do parametru help se uvádí text, který se vypíše uživateli při vyžádání nápovědy (typicky tedy jako odpověď na -h nebo --help):
Při zadávání (nejen) nápovědních textů můžete s výhodou využít některé předdefinované (rozuměno zavedením parseru) formátovací konstanty jako například:
%(prog)s
– jméno skriptu (nebo hodnota parametru prog= na konstruktoru argparse.ArgumentParser()
)
add_argument()
, tj. %(prog)s
, %(dest)s
, %(nargs)s
, %(const)s
, %(default)s
, %(type)s
, %(choices)s
a %(metavar)s
(a dokonce i %(help)s
:-)
Při výpisu nápovědy (jak v popisu usage: tak v celé nápovědě --help) jsou použita jistým způsobem upravená jména cílových proměnných pro jednotlivé argumenty:
Tyto zobrazené názvy (a pouze je, nic jiného!) můžete změnit pomocí parametru metavar=
:
Co je šikovné, tak v součinnosti s hodnotou parametru nargs můžete zadat metavars jako n-tici:
Ve výchozím nastavení rozděluje nápověda při výpisu argumenty na dvě skupiny – přepínače a poziční. Chcete-li, můžete si ale provést vlastní rozdělení do skupin za pomoci metody add_argument_group() příslušného parseru. Argumenty se pak přidávají místo parseru do těchto nově zavedených skupin:
Někdy můžete potřebovat, aby z nějaké skupiny či skupin šel vybrat pouze a jenom právě jeden argument. argparse má pro tento případ k dispozici metodu add_mutually_exclusive_group(). Navzdory podobnosti s metodou add_argument_group() nevytváří (alespoň zatím) žádné v nápovědě viditelné skupiny – uvedené argumenty jsou pouze svázány poutem exkluzivity:
Zadání argumentu z exkluzivní skupiny lze vynutit pomocí parametru required=True
:
Argumenty mohou mít nějaku hodnotu, aniž bychom je vždy museli zadávat na příkazové řádce (pokud samozřejmě nepatří mezi argumenty vyžadované). Mohou ji získat:
default=
;
Metoda set_defaults() zvítězí i nad parametrem default=, jak si snadno můžeme ověřit pomocí doplňkové metody get_default():
args.z
v tomto kódu přitom není zadatelná z příkazové řádky! Má tedy právě tu hodnotu, na jakou ji set_defaults() nastaví.
Díky metodě parse_known_args() umožňuje modul argparse zpracovat i příkazovou řádku, která obsahuje neznámé argumenty (na kterých by se metoda parse_args() s hláškou „unrecognized arguments“ zastavila). Vrací přitom dvojici, jejímž: