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": True}
UPDATE: The string should also be able to contain --long options, and words with dashes in the middle:
"-t 500 -x -c 3 -d --long-option 456 -testing weird-behaviour"
Before suggesting that I look into OptionParse module, keep in mind I don't know what the valid options are or anything like that, I am just trying to put the string into a dictionary to allow modifying it based on a different dictionary of options.
The approach I am considering is using split() to get the items into a list and then walking the list and looking for items that begin with a dash "-" and use them as the key, and then somehow getting to the next item on the list for the value. The problem I have is with options that don't have values. I thought of doing something like:
for i in range(0, len(opt_list)):
if opt_list[i][0] == "-":
if len(opt_list) > i+1 and not opt_list[i+1][0] == "-":
opt_dict[opt_list[i]] = opt_list[i+1]
else:
opt_dict[opt_list[i]] = True
But it seems like I am programming in C not Python when I do that...
eval() is an inbuilt python library function used to convert string to dictionary efficiently. For this approach, you have to import the ast package from the python library and then use it with the literal_eval() method.
Method 1: Splitting a string to generate key:value pair of the dictionary In this approach, the given string will be analysed and with the use of split() method, the string will be split in such a way that it generates the key:value pair for the creation of a dictionary.
You can use Python's regular expression to parse any string. for your requirement bellow code will give you list of variables( valiables ) and corresponding value( values ) in a list. ([\w]+)= : finds one or more alpha-numeric and underscore( _ ) characters followed by = .
There is no add() , append() , or insert() method you can use to add an item to a dictionary in Python. Instead, you add an item to a dictionary by inserting a new index key into the dictionary, then assigning it a particular value.
To handle spaces inside quotes correctly you could use shlex.split()
:
import shlex
cmdln_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)
{'--inside': True,
'--long-option': '456',
'-c': '3',
'-d': True,
'-m': True,
'-t': '500',
'-testing': 'weird -behaviour',
'-x': True}
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]] = True if not 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With