5

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?

binarybelle
  • 71
  • 1
  • 9
user2290820
  • 2,709
  • 5
  • 34
  • 62
  • 1
    Q1: what do you want? You get exactly the arguments you put, *including* the quotation marks. If you don't want that, don't surround the arguments with quotation marks. –  Jun 14 '13 at 14:11
  • http://stackoverflow.com/questions/988228/converting-a-string-to-dictionary – rectummelancolique Jun 14 '13 at 14:11
  • 1
    Q2: you confuse Python and the shell. The arguments are normally given on the shell, and that doesn't hold any idea of a Python dictionary. Hence, you can't create a Python dictionary through arguments, and, in fact, you shouldn't even try. Just make each key a separate option and use it as such. –  Jun 14 '13 at 14:12
  • @Evert you mean "--ls tomato jug andes" ?? – user2290820 Jun 14 '13 at 15:05
  • Note that this appears to me as a very unconventional way of using options. What's wrong with `python my.py --ls tomato jug andes --name man --address kac --tags don`? –  Jun 14 '13 at 16:42

2 Answers2

2

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

zmo
  • 24,463
  • 4
  • 54
  • 90
  • this is the amazing side of python.yes il look into json as well.works for me.thanks – user2290820 Jun 14 '13 at 15:15
  • so there instead of 3 methods to Json should I use JsonToDict? – user2290820 Jun 14 '13 at 15:17
  • hey, args = parser.parse_args(['--ls', 'tomato', 'jug', 'andes', '--dict', '{"name":"man", "address": "kac", "tags":"don"}']) ; with this eval(''.join(args.dict)) works as well. just saying not to write additional classes for it – user2290820 Jun 14 '13 at 15:20
  • 2
    Using `eval()` with user input is like f*cking with a stranger without a condom! DO **NEVER EVER** USE `eval()` WITH CODE THAT A USER INPUTS, you can get serious security issues. There's always another better way to do the job that has close to no security flaws. There may be good uses of `eval()` in python, but I still haven't seen one. – zmo Jun 14 '13 at 15:56
-1
import ast
dict_parser.add_argument('--dict', nargs='*',type=ast.literal_eval,default={})
args = dict_parser.parse_args(["--dict", "{'name':'man', 'address': 'kac', 'tags':'don'}"])
rectummelancolique
  • 2,247
  • 17
  • 13