I want to receive a dict(str -> str)
argument from the command line. Does argparse.ArgumentParser
provide it? Or any other library?
For the
There is a simple solution in Python 3.6 if you're simply trying to convert argparse input to a dictionary. An example is as follows:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', help='the path to the input file')
parser.add_argument('-o', '--output', help='the path to the output file')
args = parser.parse_args()
arguments = dict(args._get_kwargs())
for k, v in arguments.items():
print(k, v)
Given command line input such as python3 script_name.py --input 'input.txt' --output 'output.txt'
the code would output to terminal:
input input.txt
output output.txt
As for the current libraries like argparse, docopt and click, none of them support using dict
args. The best solution I can think of is to make a custom argparse.Action
to support it youself:
import argparse
class MyAction(argparse.Action):
def __init__(self, option_strings, dest, nargs=None, **kwargs):
super(MyAction, self).__init__(option_strings, dest, nargs, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
print '%r %r %r' % (namespace, values, option_string)
value_dict = {}
values.reverse()
while len(values) > 0:
v = eval(values.pop()).lstrip('--') # This is like crazy hack, I know.
k = eval(values.pop())
value_dict[k] = v
setattr(namespace, self.dest, value_dict)
parser = argparse.ArgumentParser()
parser.add_argument('-d', action=MyAction, nargs='*')
args = parser.parse_args('-d "--key" "key1" "--value" "val1" "--key" "key2" "--value" "val2"'.split())
print(args)
I would use something like this:
p = argparse.ArgumentParser()
p.add_argument("--keyvalue", action='append',
type=lambda kv: kv.split("="), dest='keyvalues')
args = p.parse_args("--keyvalue foo=6 --keyvalue bar=baz".split())
d = dict(args.keyvalues)
You could create a custom action which would "append" a parsed key-value pair directly into a dictionary, rather than simply accumulating a list of (key, value)
tuples. (Which I see is what skyline75489 did; my answer differs in using a single --keyvalue
option with a custom type instead of separate --key
and --value
options to specify pairs.)
Here's another solution using a custom action, if you want to specify dict key pairs together comma-separated --
import argparse
import sys
parser = argparse.ArgumentParser(description='parse key pairs into a dictionary')
class StoreDictKeyPair(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
my_dict = {}
for kv in values.split(","):
k,v = kv.split("=")
my_dict[k] = v
setattr(namespace, self.dest, my_dict)
parser.add_argument("--key_pairs", dest="my_dict", action=StoreDictKeyPair, metavar="KEY1=VAL1,KEY2=VAL2...")
args = parser.parse_args(sys.argv[1:])
print args
Running:
python parse_kv.py --key_pairs 1=2,a=bbb,c=4 --key_pairs test=7,foo=bar
Output:
Namespace(my_dict={'1': '2', 'a': 'bbb', 'c': '4', 'test': '7', 'foo': 'bar'})
If you want to use nargs instead of comma-separated values in string:
class StoreDictKeyPair(argparse.Action):
def __init__(self, option_strings, dest, nargs=None, **kwargs):
self._nargs = nargs
super(StoreDictKeyPair, self).__init__(option_strings, dest, nargs=nargs, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
my_dict = {}
print "values: {}".format(values)
for kv in values:
k,v = kv.split("=")
my_dict[k] = v
setattr(namespace, self.dest, my_dict)
parser.add_argument("--key_pairs", dest="my_dict", action=StoreDictKeyPair, nargs="+", metavar="KEY=VAL")
args = parser.parse_args(sys.argv[1:])
print args
Running
python arg_test4.py --key_pairs 1=2 a=bbb c=4 test=7 foo=bar
Outputs:
values: ['1=2', 'a=bbb', 'c=4', 'test=7', 'foo=bar']
Namespace(my_dict={'1': '2', 'a': 'bbb', 'c': '4', 'test': '7', 'foo': 'bar'})
just another easy way:
parser = argparse.ArgumentParser()
parser.add_argument('--key1')
parser.add_argument('--key2')
args = parser.parse_args()
my_dict = args.__dict__
Python receives arguments in the form of an array argv
. You can use this to create the dictionary in the program itself.
import sys
my_dict = {}
for arg in sys.argv[1:]:
key, val=arg.split(':')[0], arg.split(':')[1]
my_dict[key]=val
print my_dict
For command line:
python program.py key1:val1 key2:val2 key3:val3
Output:
my_dict = {'key3': 'val3', 'key2': 'val2', 'key1': 'val1'}
Note: args will be in string, so you will have to convert them to store numeric values.
I hope it helps.