Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Support for Enum arguments in argparse

Is there a better way of supporting Enums as types of argparse arguments than this pattern?

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()] 
like image 868
Andrzej Pronobis Avatar asked May 14 '17 19:05

Andrzej Pronobis


People also ask

How do you add arguments in Argparse?

After importing the library, argparse. ArgumentParser() initializes the parser so that you can start to add custom arguments. To add your arguments, use parser. add_argument() .

What is enum variable?

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.

What is Store_true in Python?

The store_true option automatically creates a default value of False. Likewise, store_false will default to True when the command-line argument is not present.


1 Answers

I see this is an old question, but I just came across the same problem (Python 2.7) and here's 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 defining __str__ is required to get ArgumentParser's help output to include the human readable (values) of Color.

Some sample invocations:

=> 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's question specified integers as values, here is a slightly modified version that works in that case (using the enum names, rather than the values, as the command line args):

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

The only drawback there is that a bad parameter causes an ugly KeyError. That's easily solved by adding just a bit more code, converting the lambda into a proper function.

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)) 
like image 179
ron rothman Avatar answered Oct 01 '22 19:10

ron rothman