Argparse w wierszu poleceń

Pracując w interfejsie wiersza poleceń – CLI nie sposób nie wspomnieć o module argparse. Pozwala on na definiowanie oraz dodawanie argumentów w przyjazny sposób do wywoływanego programu w wierszu poleceń. Innymi słowy umożliwia szybkie utworzenie solidnego interfejsu w CLI opartego na zdefiniowanych argumentach. Można w zasadzie to zawęzić do stworzenia parsera zawierającego ustalone argumenty, pozycyjne i/lub opcjonalne , wywołanie tego parsera i następnie jego zastosowanie przy wywoływanym skrypcie. W bardzo uproszonym skrócie pozwala nam na utworzenie systemu argumentów do wywoływanego skryptu w wierszu poleń.

Argumenty w praktyce

Posługując się wzorem na pole trójkąta równoramiennego wykorzystanie argparse w najprostszej formie może wyglądać jak poniżej:

import argparse

parser = argparse.ArgumentParser(description="Pole trójkąta równoramiennego")
parser.add_argument('bok', type=int, help ='Bok trójkąta równoramiennego')
parser.add_argument('wysokość', type=int, help ='Wysokość trójkąta równoramiennego')
argumenty = parser.parse_args()

def pole_trojkata(bok, wysokosc):
    wynik = (bok * wysokosc)/2
    return wynik

if __name__ == '__main__':
    print (pole_trojkata(argumenty.bok,argument.wysokosc))

Wywołując skrypt z dopiskiem -h widzimy pełną definicję argumentów

PS E:\Python > python powierchnia.py -h
usage: powierchnia.py [-h] bok wysokość
Pole trójkąta równoramiennego
positional arguments:
  bok         Bok trójkąta równoramiennego
  wysokość    Wysokość trójkąta równoramiennego

optional arguments:
  -h, --help  show this help message and exit

Natomiast wywołując z parametrami otrzymamy wynik

PS E:\Python > python powierchnia.py 2 4
4.0

Argumenty pozycyjne i opcjonalne

Jeżeli dodamy „–” do nazwy argumentów to staną się one opcjonalne i w przypadku nie podania zostanie wykorzystane default value, którą również ustawimy. Dodamy również krótki zapis z pojedynczymi literami i znakiem „-„

parser.add_argument('-b','--bok', type=int, help ='Bok trójkąta równoramiennego', default=1)
parser.add_argument('-w','--wysokosc', type=int, help ='Wysokość trójkąta równoramiennego', default=1)
PS E:\Python > python powierchnia.py 
0.5

Przy czym również te argumentu nie będą już pozycyjne, a więc trzeba je podawać z nazwą w wywołaniu, jeżeli taki mamy zamiar

PS E:\Python > python powierchnia.py --bok 2 --wysokosc 2 
2.0

Możemy również wywołać poprzez zapis krótki:

PS E:\Python > python powierchnia.py -b 2 -w 2 
2.0

Możemy również ustawić argumenty jako wymagane dodając parametr required = True. W takiej sytuacji oczywiście parametr default nie ma dalszego sensu.

parser.add_argument('-b','--bok', type=int, required=True,  help ='Bok trójkąta równoramiennego')
parser.add_argument('-w','--wysokosc', type=int, required=True, help ='Wysokość trójkąta równoramiennego')

Flagi store_true i store_false

Innym istotnym typem argumentu jest store_true lub store_false. Są to tzw. flagi i przetrzymują jedynie wartości prawda bądź fałsz. Czyli same w sobie są wartością i nie wymagają dopisywania niczego więcej.

Możemy nieco zmodyfikować nasz kod poprzez dodanie argumentu flagowego do drukowania opisu trójkąta. Może to wyglądać następująco:

import argparse

parser = argparse.ArgumentParser(description="Pole trójkąta równoramiennego")
parser.add_argument('-b','--bok', type=int, required=True,  help ='Bok trójkąta równoramiennego')
parser.add_argument('-w','--wysokosc', type=int, required=True, help ='Wysokość trójkąta równoramiennego')
parser.add_argument('-o','--opis', action='store_true' , help ='Opis trójkąta')
argumenty = parser.parse_args()

def pole_trojkata(bok, wysokosc):
    wynik = (bok * wysokosc)/2
    return wynik

if __name__ == '__main__':
    pole = pole_trojkata(argumenty.bok,argumenty.wysokosc)
    if argumenty.opis:
        print("Trójkąt o boku długości %s i wysokości %s ma pole o powierzchni %s." % (argumenty.bok, argumenty.wysokosc, pole))
    else:
        print (pole)

Wtedy wywołanie z parametrem „-o” będzie wyglądało jak niżej

PS E:\Python > python powierchnia.py -b 2 -w 2 -o
Trójkąt o boku długości 2 i wysokości 2 ma pole o powierzchni 2.0.

Czytelniejszy help z metavar

Często wykorzystywanym parametrem jest matavar, który definiuje wyświetlaną nazwę argumentu w help. Najczęściej ustawianie tego jako pustego znaku znacząco zwiększa czytelność komendy help paresera. Przykładowo dla obecnego skryptu komenda -h zwróci poniższe:

usage: powierchnia.py [-h] -b BOK -w WYSOKOSC [-o]

Pole trójkąta równoramiennego

optional arguments:
  -h, --help            show this help message and exit
  -b BOK, --bok BOK     Bok trójkąta równoramiennego
  -w WYSOKOSC, --wysokosc WYSOKOSC
                        Wysokość trójkąta równoramiennego
  -o, --opis            Opis trójkąta

Natomiast dodanie parametru  metavar=” w argumentach bok i wysokość

parser.add_argument('-b','--bok', type=int, required=True, metavar='', help ='Bok trójkąta równoramiennego')
parser.add_argument('-w','--wysokosc', type=int, required=True, metavar='',help ='Wysokość trójkąta równoramiennego')

Da nam poniższy rezultat:

usage: powierchnia.py [-h] -b  -w  [-o]

Pole trójkąta równoramiennego

optional arguments:
  -h, --help        show this help message and exit
  -b , --bok        Bok trójkąta równoramiennego
  -w , --wysokosc   Wysokość trójkąta równoramiennego
  -o, --opis        Opis trójkąta

W tym przypadku jest to znacznie czytelniejsza forma.

Konkluzja

Argparse jest niezwykle użyteczną formą organizowania argumentów w wierszu poleceń. Pozwala w prosty sposób ustandaryzować wykorzystywanie i uruchamianie skryptów w CLI. Warto również wspomnieć, że jest częścią biblioteki standardowej.

Dodaj komentarz