Skip to content Skip to sidebar Skip to footer

How To Parse An Arbitrary Option String Into A Python Dictionary

I am trying to find the most Pythonic way to take a string containing command line options: '-t 500 -x -c 3 -d' And turn it into a dictionary {'-t':'500', '-x':True, '-c':'3', '-d

Solution 1:

To handle spaces inside quotes correctly you could use shlex.split():

importshlexcmdln_args= ('-t 500 -x -c 3 -d --long-option 456 '
              '-testing "weird -behaviour" -m "--inside"')

args = shlex.split(cmdln_args)
options = {k: True if v.startswith('-') else v
           for k,v in zip(args, args[1:]+["--"])if k.startswith('-')}

from pprint import pprint
pprint(options)

Output

{'--inside': True,
 '--long-option': '456',
 '-c': '3',
 '-d': True,
 '-m': True,
 '-t': '500',
 '-testing': 'weird -behaviour',
 '-x': True}

Solution 2:

You could use regular expressions like so:

import re

args = "-t 500 -x -c 3 -d --long-option 456 -testing weird-behaviour"
matches = re.findall(r'(--?[\w-]+)(.*?)(?= -|$)', args)

result = {}
for match in matches:
    result[match[0]] = Trueifnot match[1] else match[1].strip()

print result

and the result is equal to

{
'-d': True, 
'-c': '3', 
'-t': '500', 
'--long-option': '456', 
'-x': True, 
'-testing': 'weird-behaviour'
}

Regular Expression breakdown:

(--?[\w-]+)(.*?)(?= -|$)

  • (--?[\w-]+) matches any character or word (dashes allowed in the word) that starts with a "-" or a "--".
  • (.*?) matches any character 0 or more times in a non-greedy or minimal fashion by using the question mark.
  • (?= -|$) is a positive lookahead. It checks that what we are looking for is followed by a " -" or the end of the string but it does not include it in the match.

Note the use of parenthesis in this regular expression. These are used to create groups so when we call findall it will split them into tuples.

Solution 3:

Argument Parsing for Humans - https://github.com/kennethreitz/args

Solution 4:

I can't speak to the most Pythonic way, but here's a 1-liner:

opt_list = "-t 500 -x -c 3 -d"

dict((e iflen(e) >1else (e[0],True) for e in(elem.split()for elem in('-'+d for d in opt_list.split('-')if d))))

>>>{'-t': '500', '-x': True, '-c': '3', '-d': True}

[Edit: As Matthias pointed out, this won't work for values with a '-' in them]

...however, in general, I don't think the OP's answer can be solved unambiguously when you allow a '-' in option values.

consider these simple options:

"-a -b"

Is this:

  • {'-a': '-b'},
  • {'a-':True, '-b':True}

???

Solution 5:

>>>results = "-t 500 -x -c 3 -d".split()>>>rd = {}>>>while i < len(results):...if results[i].startswith("-"):...      rd[results[i]]=True...try:...ifnot results[i+1].startswith("-"):...            rd[results[i]] = results[i+1]...except IndexError: pass...   i+=1...>>>rd
{'-t': '500', '-x': True, '-c': '3', '-d': True}

but pretty simillar to what you have..

Post a Comment for "How To Parse An Arbitrary Option String Into A Python Dictionary"