JiriHnidek
JiriHnidek

Reputation: 563

Python: How to get all default values from argparse

When module optparse is used, then I can get all default values for all command line arguments like this:

import optparse

if __name__ == '__main__':
    parser = optparse.OptionParser(usage='pokus --help')
    parser.add_option("-d", "--debug", action='store_true', dest="debug",
                      default=False, help='Enabling debugging.')
    options, args = parser.parse_args()
    print(parser.defaults)

Since optparse is deprecated it is wise to rewrite your code to use argparse module. However I can't find any way how to get all default values of all command line arguments added to parser object:

import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser(usage='pokus --help')
    parser.add_argument("-d", "--debug", action='store_true', dest='debug',
                        default=False, help='Enabling debugging.')   
    args = parser.parse_args()
    # <---- How to get default values for all arguments here?
    # Not: vars(args)

I want to get all default values when I run program with (./app.py -d) or without any command line argument (./app.py).

Upvotes: 13

Views: 13836

Answers (5)

JohanL
JohanL

Reputation: 6891

If you do not want to parse an empty input string, you can use the method get_default in the parser object:

import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser(usage='pokus --help')
    parser.add_argument("-d", "--debug", action='store_true', dest='debug',
                        default=False, help='Enabling debugging.')   
    args = parser.parse_args()

    # To get a single default:
    d_default = parser.get_default('d')

    # To get all defaults:
    all_defaults = {}
    for key in vars(args):
        all_defaults[key] = parser.get_default(key)

    # Edit: Adding an alternative one-liner (using dict comprehension):
    all_defaults = {key: parser.get_default(key) for key in vars(args)}

Upvotes: 16

David258
David258

Reputation: 757

Somewhat late to the party, but this is a function (with bonus unittest) that I've used in a couple of cases to get hold of the default arguments without having to parse first (parsing first can be annoying if you have required arguments that aren't available yet)

def get_argparse_defaults(parser):
    defaults = {}
    for action in parser._actions:
        if not action.required and action.dest != "help":
            defaults[action.dest] = action.default
    return defaults

def get_argparse_required(parser):
    required = []
    for action in parser._actions:
        if action.required:
            required.append(action.dest)
    return required

parser = argparse.ArgumentParser()
optional_defaults_dict = get_argparse_defaults(parser)
required_list = get_argparse_required(parser)

class TestDefaultArgs(unittest.TestCase):

    def test_get_args(self):
        parser = argparse.ArgumentParser()
        parser.add_argument('positional_arg')
        parser.add_argument('--required_option', required=True)
        parser.add_argument('--optional_with_default', required=False, default="default_value")
        parser.add_argument('--optional_without_default', required=False)

        required_args = get_argparse_required(parser)
        self.assertEqual(['positional_arg', 'required_option'], required_args)


        default_args = get_argparse_defaults(parser)
        self.assertEqual({'optional_with_default': 'default_value',
                          'optional_without_default': None},
                         default_args)

Upvotes: 7

imz22
imz22

Reputation: 2938

For the above example:

import argparse

if __name__ == '__main__':
   parser = argparse.ArgumentParser(usage='pokus --help')
   parser.add_argument("-d", "--debug", action='store_true', dest='debug',
                    default=False, help='Enabling debugging.') 

A. To get all the values with their defaults in a tuple format:

In[1]: args = parser.parse_known_args()[0]
In[2]: args._get_kwargs()
Out[1]: [('debug', False)]

to access to each item:

In[3]: args.debug
Out[2]: False

B. To get the values and their default as dictionary format

In[4]: dict_args = parser.parse_known_args()[0].__dict__
In[5]: dict_args
Out[3]: {'debug': False}

And to access each key:

In[6]: dict_args['debug']
Out[4]: False

Or print them iteratively:

In[7]: for key in dict_args:
...        print('value for %s is: %s'% (key, dict_args[key]))

Out[5]: value for debug is: False

Upvotes: 1

hpaulj
hpaulj

Reputation: 231605

For your information, here's the code, at the start of parsing that initializes the defaults:

def parse_known_args(...):
    ....
    # add any action defaults that aren't present
    for action in self._actions:
        if action.dest is not SUPPRESS:
            if not hasattr(namespace, action.dest):
                if action.default is not SUPPRESS:
                    setattr(namespace, action.dest, action.default)

    # add any parser defaults that aren't present
    for dest in self._defaults:
        if not hasattr(namespace, dest):
            setattr(namespace, dest, self._defaults[dest])
    ...

So it loops through the parser._actions list, collecting the action.default attribute. (An action is a Action class object that was created by the parser.add_argument method.). It also checks self._defaults. This is the dictionary modified by a parse.set_defaults method. That can be used to set defaults that aren't linked directly to an action.

After parsing the command line, default strings in the namespace may be evaluated (with the action.type), turning, for example a default='1' into an integer 1.

Handling of defaults in argparse isn't trivial. Your parse_args([]) probably is simplest, provided the parser is ok with that (i.e. doesn't have any required arguments).

I don't know now optparse sets the defaults attribute. There is a non-trival method, optparse.OptionParser.get_default_values.

Upvotes: 2

JiriHnidek
JiriHnidek

Reputation: 563

I found solution:

import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser(usage='pokus --help')
    parser.add_argument("-d", "--debug", action='store_true', dest='debug',
                        default=False, help='Enabling debugging.')
    parser.add_argument("-e", "--example", action='store', dest='example',
                        default="", help='Example of argument.')
    # Arguments from command line and default values
    args = vars(parser.parse_args())
    # Only default values
    defaults = vars(parser.parse_args([]))

Then you can compare args and defaults values and distinguish between default values and values from command line.

Upvotes: 18

Related Questions