argparse - wywołanie funkcji via wartość przekazywanego argumentu

0

Mam pewną zagwozdkę z obsługą parametrów linii poleceń z wykorzystaniem argparse. Poniższe to uproszczony fragment:

parser = argparse.ArgumentParser()
parser.add_argument('-a','--action', help='Execute specific use case',
                    choices=['case1','case2','case3'],
                    default='case1',
                    dest='action')

Gdzieś tam dalej w kodzie zdefiniowana jest logika danej komendy/przypadku użycia:

def case1():
...

Mam więc parametr, przez który przekazywane są nazwy funkcji i argparse pilnuje by były przekazywane tylko dozwolone nazwy.

Mogę sobie napisać generyczny kawałek kodu + słownik mapujący nazwę funkcji na funkcję i to działa:

command= COMMNADS_MAP[args.action]
command()

Czy da się to zrealizować inaczej, bez konieczności utrzymywania słownika? Może jakaś ciekawa funkcjonalność argparse, o której nie wiem?

--edited:
Pewnie mógłbym sklecić coś na zasadzie:

  locals()[args.action]() 

Tylko czy to mieści się w pythonowych dobrych praktykach?

3

Z tego co kojarzę, chyba w żadnym języku nie jest zalecana ewaluacja tekstu, szczególnie jeśli może pochodzić z inputu ;)

Słownik jest o tyle wygodnym podejściem, że później jako argument choices możesz podać slownik.keys(), w słowniku trzymasz dozwolone klasy / metody / funkcje i tyle.

Znaczy, to oczywiście może być złe i niepythoniczne podejście, ale np. type hints też zostały wyklęte przez twardogłowych jako niepythoniczne, ale i tak wolę ich używać żeby ograniczyć bałagan w kodzie.

0

Btw. Jak bardzo chcesz przyszpanować, to zawsze możesz przeładować sobie metodę __contains__ listy tak, by zwracała coś w stylu:

return item in [element.__name__ for element in self]

I trzymać sobie dozwolone funkcje w takiej liście na sterydach, i przekazywać ją bezpośrednio do choices - tylko to taki trochę overkill :p

Chociaż jak potrzebowałem jakoś przekazać do choices ciągły zakres liczb zmiennoprzecinkowych, to takie przeładowanie __contains__ ładnie załatwiło sprawę, bo zamiast ifozy mogłem przekazać taki argument:

Range(0.0, 50.0)
0

Dzięki @superdurszlak za wypowiedzi :-) Chcę upraszczać, ale nie poza granice zdrowego rozsądku. Obecnie mam implementację w oparciu o słownik, ale ciekaw byłem alternatyw w celach edukacyjnych.

1

Ja bym polecał docopta: https://github.com/docopt/docopt
Co prawda też domyślnie jest słownik, ale jest prostszy i czytelniejszy (IMO) niż argparse

1 użytkowników online, w tym zalogowanych: 0, gości: 1