2

Is there any library that can parse random key value pairs in sys.argv in Python?

For example:

 python run.py --v1 k1 --v2 k2 --v3 k3

Should return me a dictionary like {v1->k1, v2->k2, v3->k3}. and at compile time I don't know what those 'v' will be.

Thanks!

Erben

Trevor
  • 7,777
  • 6
  • 31
  • 50
Erben Mo
  • 3,528
  • 3
  • 19
  • 32

3 Answers3

1
d = {}
for i,arg in enumerate(sys.argv):
    if arg.startswith("--"):
        d[arg[2:]] = sys.argv[i+1]

print d
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
  • 1
    This solution would give quite unexpected results for consecutive keys with no values inbetween (e.g. when run with `--foo --bar --baz` parameters) – lanzz Feb 20 '14 at 22:31
  • 1
    yeah it would ... but thats not the input the OP specified. .. if its as narrow as his example this would work fine :P ... if he needs more smarts in it... its easy enough to change to suite the needs of something simple ... if he needs something more advanced he should use the `--var name=val` syntax suggested in the comments – Joran Beasley Feb 20 '14 at 22:33
1

It's kind of hacky, but you do have this:

import argparse
import collections
parser = argparse.ArgumentParser()
known, unknown_args = parser.parse_known_args()

unknown_options = collections.defaultdict(list)
key = None
for arg in unknown_args:
    if arg.startswith('--'):
        key = arg[2:]
    else:
        unknown_options[key].append(arg)
wim
  • 338,267
  • 99
  • 616
  • 750
  • So basically this solution leaves the asker exactly where he started — needing a library to parse a list of unanticipated options. Also it can be easily optimized down to `unknown_args = sys.argv`, as that's what it actually does. – lanzz Feb 20 '14 at 22:33
  • Oh you're right that's pretty crap. I've added some more code now. – wim Feb 20 '14 at 22:44
  • btw sys.argv has other stuff in it like the script name – wim Feb 20 '14 at 22:48
  • Still not perfect becasue we have to manually search for "--" in the unknown_args. But one problem that parse_known_args sovles is it returns unknown_args regardless of the ordering. i.e. you can have --known_k1 v1 --unknown_k2 v2 --known_k3 v2 and it will filter out the known args – Erben Mo Feb 20 '14 at 23:02
  • `argparse` starts with `sys.argv[1:]`. If there aren't other arguments to handle, you could skip the `argparse` part. – hpaulj Feb 21 '14 at 06:04
0

In a newer Python that uses dictionary comprehension you could use a one liner like this:

ll = sys.argv[1:]
args = {k[2:]:v for k,v in zip(ll[::2], ll[1::2])}
# {'v1': 'k1', 'v2': 'k2', 'v3': 'k3'}

It doesn't have any flexibility in case your user screws up the pairing, but it would be a quick start.

A generator could be used to pop pairs of strings off the sys.argv[1:]. This would be a good place to build in flexibility and error checking.

def foo(ll):
    ll = iter(ll)
    while ll:
        yield ll.next()[2:], ll.next()
{k:v for k,v in foo(ll)}
hpaulj
  • 221,503
  • 14
  • 230
  • 353