2017-05-14 17 views
5

Czy istnieje lepszy sposób na obsługę Enums jako typów argparse argumentów niż ten wzór?Obsługa argumentów Enum w argparse

class SomeEnum(Enum): 
    ONE = 1 
    TWO = 2 

parser.add_argument('some_val', type=str, default='one', 
        choices=[i.name.lower() for i in SomeEnum]) 
... 
args.some_val = SomeEnum[args.some_val.upper()] 
+1

Pojawił się wniosek o "Enum" na błędy/problemy w Pythonie. Nie przypominam sobie zbytniego entuzjazmu dla dodatkowej specjalnej obsługi. Wybory takie jak twoje są jednym ze sposobów. Inną jest niestandardowa funkcja 'type'. To może sprawdzić i przekonwertować. Podejrzewam, że znasz Enums bardziej niż ja. – hpaulj

+0

Zastanawiam się przez chwilę, czy byłoby możliwe wyprowadzenie niestandardowej Enum, która zachowałaby się zgodnie z oczekiwaniami, gdy ustawiona jako 'type =' –

+0

Parametr 'type' jest funkcją/wywoływalną. Napisz własny, który bierze ciąg i coś z nim robi. Typy wspólne, 'int' i' float' są standardowymi funkcjami, które wykonują 'int (" 123 ")' lub 'float (" 12.3 ")'. – hpaulj

Odpowiedz

7

widzę jest to stara sprawa, ale ja po prostu natknął się na ten sam problem (Python 2.7) i oto jak I rozwiązać go:

from argparse import ArgumentParser 
from enum import Enum 

class Color(Enum): 
    red = 'red' 
    blue = 'blue' 
    green = 'green' 

    def __str__(self): 
     return self.value 

parser = ArgumentParser() 
parser.add_argument('color', type=Color, choices=list(Color)) 

opts = parser.parse_args() 
print 'your color was:', opts.color 

Zauważ, że definiowanie __str__ jest wymagany do uzyskania ArgumentParser ' s pomoc wyjściowa do włączenia czytelne dla człowieka (wartości) z Color.

Niektóre przykładowe wywołania:

=> python enumtest.py blue 
your color was: blue 

=> python enumtest.py not-a-color 
usage: enumtest.py [-h] {blue,green,red} 
enumtest.py: error: argument color: invalid Color value: 'not-a-color' 

=> python enumtest.py -h 
usage: enumtest.py [-h] {blue,green,red} 

positional arguments: 
    {blue,green,red} 

Ponieważ zapytania podano liczb PO jako wartości, tutaj jest nieco zmodyfikowaną wersją, która działa w tym przypadku (używając nazwy enum, zamiast wartości, jak args linii komend):

class Color(Enum): 
    red = 1 
    blue = 2 
    green = 3 

    def __str__(self): 
     return self.name 

parser = ArgumentParser() 
parser.add_argument('color', type=lambda color: Color[color], choices=list(Color)) 

Jedyną wadą jest fakt, że zły parametr powoduje brzydki KeyError. Można to łatwo rozwiązać, dodając nieco więcej kodu, przekształcając lambdę w odpowiednią funkcję.

class Color(Enum): 
    red = 1 
    blue = 2 
    green = 3 

    def __str__(self): 
     return self.name 

    @staticmethod 
    def from_string(s): 
     try: 
      return Color[s] 
     except KeyError: 
      raise ValueError() 

parser = ArgumentParser() 
parser.add_argument('color', type=Color.from_string, choices=list(Color)) 
Powiązane problemy