I would like to pass an arbitrary set of arguments in the format --arg1 value1
to my python script and retrieve them in a dictionary of the kind {'arg1': 'value1}
. I want to use argparse
to achieve that. The function parse_known_args
allows for extra args, but they can be retrieved as a simple list and are not named.

- 453
- 1
- 4
- 15
-
you can simply define the option using the `add_argument` method. `parse_known_args` is a method that will parse all the options defined via `add_argument` and return the remaining command line, while using `parse_args` will raise an error if there are left over arguments. – Bakuriu Sep 07 '16 at 11:32
-
The extra arguments can be of any name/value, not known a priori. – Fabrizio Demaria Sep 07 '16 at 11:34
-
Then `argparse` has no chance of knowing what to do with it. That is the point of `parse_known_args`: **you** have to manually handle the remaining arguments as you please. – Bakuriu Sep 07 '16 at 11:36
-
Alternatively you could change your syntax from `--arg value` to something like `--define arg value` and define a custom `Action` that will do what you want. – Bakuriu Sep 07 '16 at 11:38
-
I see your point. My idea was mainly to have a cmd line syntax like `... --arg1 val1` and `argparse` would make a dictionary like `extra_args = {"arg1": "val1"}`. But I guess there is no such option and I have to build the dictionary myself. – Fabrizio Demaria Sep 07 '16 at 11:42
2 Answers
A better idea is to define one option that takes two arguments, a name and a value, and use a custom action to update a dictionary using those two arguments.
class OptionAppend(Action):
def __call__(self, parser, namespace, values, option_string):
d = getattr(namespace, self.dest)
name, value = values
d[name] = value
p.add_argument("-o", "--option", nargs=2, action=OptionAppend, default={})
Then instead of myscript --arg1 value1 --arg2 value2
, you would write myscript -o arg1 value1 -o arg2value1
, and after args = parser.parse_args()
, you would have args.o == {'arg1': 'value1, 'arg2': 'value2'}
.
This is somewhat analogous to the use of a list or dictionary to hold a set of related variables, instead of a set of individually named variables.
# Good
v = [x, y, z]
v = { 'key1': x, 'key2': y, 'key3': z}
# Bad
v1 = x
v2 = y
v3 = z

- 497,756
- 71
- 530
- 681
The question of handling arbitrary key/value pairs has come up a number of times. argparse
does not have a builtin mechanism for that.
Is it possible to use argparse to capture an arbitrary set of optional arguments? (almost a duplicate from last May)
Your idea of using parse_know_args
and then doing your own dictionary build from the extras
is good - and perhaps the simplest. How you handle the extras list will depend on how well behaved your users are (predicable '--key', 'value'
pairs). This basically the same as if you parsed sys.arv[1:]
directly.
If the user gives input like --options key1:value1 key2=value2 "key3 value3"
you can parse those pairs in a custom Action class (e.g. split the string on the delimiter etc).
Input like --options "{key1: value1, key2: value2}"
can be handled as a JSON
string, with a type function like: type=json.load
(I'd have to look that up).