William
William

Reputation: 45

Python convert dictionary to argparse

Right now, I have a script that can accept command line arguments using argparse. For example, like this:

#foo.py
def function_with_args(optional_args=None):
  parser = argparse.ArgumentParser()
  # add some arguments
  args = parser.parse_args(optional_args)
  # do something with args

However, I'd like to be able to use this function with a dictionary instead, for example with something like this:

def function_using_dict(**kwargs):
  # define parser and add some arguments
  args = parser.parse_dict_args(kwargs)
  # everything else is the same

Note that I have a lot of arguments with default values in argparse which I'd like to use, so the following wouldn't work:

def function_no_default_args(**kwargs):
  args = kwargs # not using default values that we add to the parser!

Upvotes: 4

Views: 7399

Answers (3)

user1487399
user1487399

Reputation: 1

import argparse
config_dict = {'width': 1920, 'height': 1080}
namespace = argparse.Namespace(**config_dict)

Source.

Upvotes: 0

hpaulj
hpaulj

Reputation: 231385

argparse.Namespace is a relatively simple object subclass, with most of its code devoted to displaying the attributes (as print(args) shows). Internally parse_args uses get_attr and set_attr to access the namespace, minimizing the assumptions about attributes names.

When using subparsers, the subparser starts with a 'blank' namespace, and uses the following code to copy its values to the main namespace.

    # In case this subparser defines new defaults, we parse them
    # in a new namespace object and then update the original
    # namespace for the relevant parts.
    subnamespace, arg_strings = parser.parse_known_args(arg_strings, None)
    for key, value in vars(subnamespace).items():
        setattr(namespace, key, value)

Originally the main namespace was passed to the subparser, eg. parser.parse_known_args(arg_strings, namespace), but the current version lets the subparser defaults take priority.

Handling defaults is a bit complicated. If you don't have any required arguments then

 args = parser.parse_args([])

will set all the defaults. Or you could look at the start of parse.parse_known_args to see how defaults are inserted into the namespace at the start of parsing. Just beware that there's an added step at the end of parsing that runs remaining defaults through their respective type functions.

Upvotes: 3

Ben Y
Ben Y

Reputation: 1023

If you are trying to convert the result of parse_args into a dict, you can probably just do this:

kwargs = vars(args)

After your comment, I thought about it. Going to go with your existing function.

#foo.py
def function_with_args_and_default_kwargs(optional_args=None, **kwargs):
  parser = argparse.ArgumentParser()
  # add some arguments
  # add the other arguments
  for k, v in kwargs.items():
    parser.add_argument('--' + k, default=v)
  args = parser.parse_args(optional_args)
  # do something with args

Upvotes: 1

Related Questions