Support for Enum arguments in argparse

Is there a better way to support Enums as argparse argument types than this template?

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()]
+20
source share
3 answers

I see that this is an old question, but I ran into the same problem (Python 2.7), and here is how I solved it:

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

Note that for a definition ArgumentParserto be output, you ArgumentParsermust specify __str__to enable human readable (values) Color.

Some sample queries:

=> 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}

Since the OP question sets integers as values, here is a slightly modified version that works in this case (using enumeration names, not values, as indicated on the command line):

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))

, KeyError. , , .

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))
+40
+1

. , __repr__ to_string, argparse argparse .

import argparse
import enum


class SomeEnum(enum.IntEnum):
    ONE = 1
    TWO = 2

    # magic methods for argparse compatibility

    def __str__(self):
        return self.name.lower()

    def __repr__(self):
        return str(self)

    @staticmethod
    def argparse(s):
        try:
            return SomeEnum[s.upper()]
        except KeyError:
            return s


parser = argparse.ArgumentParser()
parser.add_argument('some_val', type=SomeEnum.argparse, choices=list(SomeEnum))
args = parser.parse_args()
print('success:', type(args.some_val), args.some_val)

, yellow , :

demo.py: error: argument color: invalid from_string value: 'yellow'

, three , :

demo.py: error: argument some_val: invalid choice: 'three' (choose from one, two)

IMHO, in the simple case of simply converting the name of the members of an enumeration to lowercase, the OP method seems simpler. However, for more complex conversion cases, this may be useful.

0
source

Source: https://habr.com/ru/post/1017251/


All Articles