You want to create a series of key-value pairs from the command line, using the argparse library, e.g.:
command par1 par2 --set foo=hello bar="hello world" baz=5
This is typically useful when you want to clearly distinguish":
- Ordinary arguments for the command-line utility itself (output, input, format, etc.) from
- A set of key-value pairs you want to pass to the python application. This is especially valid when you do not want that set of values to be predetermined, as this can save a lot of code.
This possibility changes somewhat the way we look at argparse.
import argparse
parser = argparse.ArgumentParser(description="...")
...
parser.add_argument("--set",
metavar="KEY=VALUE",
nargs='+',
help="Set a number of key-value pairs "
"(do not put spaces before or after the = sign). "
"If a value contains spaces, you should define "
"it with double quotes: "
'foo="this is a sentence". Note that '
"values are always treated as strings.")
args = parser.parse_args()
The argument is optional and multivalued, with a minimum of one occurrence (nargs='+'
).
The result is a list of strings e.g. ["foo=hello", "bar=hello world", "baz=5"]
in args.set
, which we now need to parse (note how the shell has processed and removed the quotes!).
def parse_var(s):
"""
Parse a key, value pair, separated by '='
That's the reverse of ShellArgs.
On the command line (argparse) a declaration will typically look like:
foo=hello
or
foo="hello world"
"""
items = s.split('=')
key = items[0].strip() # we remove blanks around keys, as is logical
if len(items) > 1:
# rejoin the rest:
value = '='.join(items[1:])
return (key, value)
def parse_vars(items):
"""
Parse a series of key-value pairs and return a dictionary
"""
d = {}
if items:
for item in items:
key, value = parse_var(item)
d[key] = value
return d
# parse the key-value pairs
values = parse_vars(args.set)
Now the variable values
contains a dictionary with the key-value pairs defined on the command line:
values = {'foo':'hello', 'bar':'hello world', 'baz':'5'}
Note that the values are always returned as strings.
Nice work. Note that you can avoid the rejoining of a value if you limit the string splitting, as in
items = s.split('=', 1)
.