Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you convert command line args in python to a dictionary?

I'm writing an application that takes arbitrary command line arguments, and then passes them onto a python function:

$ myscript.py --arg1=1 --arg2=foobar --arg1=4

and then inside myscript.py:

import sys
argsdict = some_function(sys.argv)

where argsdict looks like this:

{'arg1': ['1', '4'], 'arg2': 'foobar'}

I'm sure there is a library somewhere that does this, but I can't find anything.

EDIT: argparse/getopt/optparse is not what I'm looking for. These libraries are for defining an interface that is the same for each invocation. I need to be able to handle arbitrary arguments.

Unless, argparse/optparse/getopt has functionality that does this...

like image 785
priestc Avatar asked Oct 09 '12 19:10

priestc


People also ask

How do you convert args to string in Python?

Python has a built-in function str() which converts the passed argument into a string format. The str() function returns a string version of an object. The object can be int , char , or a string . If the object is not passed as an argument, then it returns an empty string.

How do you pass arguments to a Python program?

In Python, arguments are passed to a script from the command line using the sys package. The argv member of sys ( sys. argv ) will store all the information in the command line entry and can be accessed inside the Python script. Python's getopt module can also be used to parse named arguments.


2 Answers

You can use something like this:

myscript.py

import sys
from collections import defaultdict

d=defaultdict(list)
for k, v in ((k.lstrip('-'), v) for k,v in (a.split('=') for a in sys.argv[1:])):
    d[k].append(v)

print dict(d)

Result:

C:\>python myscript.py  --arg1=1 --arg2=foobar --arg1=4
{'arg1': ['1', '4'], 'arg2': ['foobar']}

Note: the value will always be a list, but I think this is more consistent. If you really want the final dictionary to be

{'arg1': ['1', '4'], 'arg2': 'foobar'}

then you could just run

for k in (k for k in d if len(d[k])==1):
    d[k] = d[k][0]

afterwards.

like image 116
sloth Avatar answered Sep 28 '22 04:09

sloth


Here's an example using argparse, although it's a stretch. I wouldn't call this complete solution, but rather a good start.

class StoreInDict(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        d = getattr(namespace, self.dest)
        for opt in values:
            k,v = opt.split("=", 1)
            k = k.lstrip("-")
            if k in d:
                d[k].append(v)
            else:
                d[k] = [v]
        setattr(namespace, self.dest, d)

# Prevent argparse from trying to distinguish between positional arguments
# and optional arguments. Yes, it's a hack.
p = argparse.ArgumentParser( prefix_chars=' ' )

# Put all arguments in a single list, and process them with the custom action above,
# which convertes each "--key=value" argument to a "(key,value)" tuple and then
# merges it into the given dictionary.
p.add_argument("options", nargs="*", action=StoreInDict, default=dict())

args = p.parse_args("--arg1=1 --arg2=foo --arg1=4".split())
print args.options
like image 32
chepner Avatar answered Sep 28 '22 04:09

chepner