Python argparse dict arg

前端 未结 9 1675
不知归路
不知归路 2021-02-01 04:31

I want to receive a dict(str -> str) argument from the command line. Does argparse.ArgumentParser provide it? Or any other library?

For the

相关标签:
9条回答
  • 2021-02-01 04:34

    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
    
    0 讨论(0)
  • 2021-02-01 04:38

    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)
    
    0 讨论(0)
  • 2021-02-01 04:41

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

    0 讨论(0)
  • 2021-02-01 04:47

    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'})
    
    0 讨论(0)
  • 2021-02-01 04:49

    just another easy way:

    parser = argparse.ArgumentParser()
    parser.add_argument('--key1')
    parser.add_argument('--key2')
    args = parser.parse_args()
    my_dict = args.__dict__
    
    0 讨论(0)
  • 2021-02-01 04:49

    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.

    0 讨论(0)
提交回复
热议问题