Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Parse multiple datatypes using argparse

I tried using argparse to learn how it works to parse a given list:

parser = argparse.ArgumentParser()

parser.add_argument('--ls', nargs='*', type=str, default = [])
Out[92]: _StoreAction(option_strings=['--ls'], dest='ls', nargs='*', const=None, default=[], type=<type 'str'>, choices=None, help=None, metavar=None)

args = parser.parse_args("--ls 'tomato' 'jug' 'andes'".split())

args
Out[94]: Namespace(ls=["'tomato'", "'jug'", "'andes'"])

args.ls
Out[96]: ["'tomato'", "'jug'", "'ande'"]

args.ls[0]
Out[97]: "'tomato'"

eval(args.ls[0])
Out[98]: 'tomato'

Q1: The above works but Is there a better way to access values in the list?

Then I tried it with dictionary to parse a dictionary given:

dict_parser = argparse.ArgumentParser()
dict_parser.add_argument('--dict', nargs='*',type=dict,default={})

Out[104]: _StoreAction(option_strings=['--dict'], dest='dict', nargs='*', const=None, default={}, type=<type 'dict'>, choices=None, help=None, metavar=None)

arg2 = dict_parser.parse_args("--dict {'name':'man', 'address': 'kac', 'tags':'don'}")
usage: -c [-h] [--dict [DICT [DICT ...]]]
-c: error: unrecognized arguments: - - d i c t   { ' n a m e ' : ' m a n' ,   ' a d d r e s s ' :   ' k a c' ,   ' t a g s ' : ' d o n ' }
To exit: use 'exit', 'quit', or Ctrl-D.
An exception has occurred, use %tb to see the full traceback.

SystemExit: 2

And that doesn't work. Q2: How does the above work for dictionary?

Q3: Now I want

python my.py --ls tomato jug andes  --dict {'name':'man', 'address': 'kac', 'tags':'don'}

to be parsed

How do I do that?

I referred to http://parezcoydigo.wordpress.com/2012/08/04/from-argparse-to-dictionary-in-python-2-7/

...and found assigning everything under a dictionary is pretty useful. Could somebody simplify this task so as to parse multiple datatypes in the arguments?

like image 926
user2290820 Avatar asked Nov 12 '22 03:11

user2290820


1 Answers

parser.add_argument('--ls', nargs='*', type=str, default = []) Q1: The above works but Is there a better way to access values in the list?

As I often consider "simpler is better", and this is a really simple way to do things, I'd say there is no better way. But still, there are other ways.

dict_parser.add_argument('--dict', nargs='*',type=dict,default={}) arg2 = dict_parser.parse_args("--dict {'name':'man', 'address': 'kac', 'tags':'don'}") Q2: How does the above work for dictionary?

I'd advice you to parse your string using json:

>>> class FromJSON():
...     def __init__(self, string):
...         self.string = string
...     def decode(self):
...         return json.loads(self.string)
...    
>>> dict_parser.add_argument('--dict',type=FromJSON)
>>> arg2 = dict_parser.parse_args(['--dict', '{"name":"man", "address": "kac", "tags":"don"}'])

though JSON is a lot like python, it is not python. It is picky about quoting (values are surrounded by double quotes only) and about (having no) trailing commas. But at least it is safe against code injection! And of course you shall surround your parameter with quotes

You may have anoter solution to give a dict as parameters, it would be to get rid of the brackets:

>>> parser.add_argument('--dict', nargs='*', type=str, default = [])
>>> args = parser.parse_args(['--dict', 'name:man', 'address:kac', 'tags:don'])
>>> args.dict = dict([arg.split(':') for arg in args.dict])
>>> print args.dict
{'tags': 'don', 'name': 'man', 'address': 'kac'}

Q3: Now I want

python my.py --ls tomato jug andes  --dict {'name':'man', 'address': 'kac', 'tags':'don'}

to be parsed

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--dict', type=FromJSON, default=FromJSON("{}"))
>>> parser.add_argument('--ls', nargs='*', type=str, default = [])
>>> args = parser.parse_args(['--ls', 'tomato', 'jug', 'andes', '--dict', '{"name":"man", "address": "kac", "tags":"don"}'])
>>> args.ls
['tomato', 'jug', 'andes']
>>> args.dict
<__main__.FromJSON instance at 0x7f932dd20c20>
>>> args.dict.decode()
{u'tags': u'don', u'name': u'man', u'address': u'kac'}

About FromJSON(), it can be improved so it is something like:

class JsonToDict():
    def __call__(self, string):
        return json.loads(string)

that you could use as follows:

dict_parser.add_argument('--dict',type=JsonToDict())

HTH

like image 95
zmo Avatar answered Nov 15 '22 00:11

zmo