Python: 如何从argparse获取所有默认值

11

当使用模块optparse时,我可以像这样获取所有命令行参数的默认值:

当使用optparse模块时,我可以通过以下方式获取所有命令行参数的默认值:

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)

由于optparse已经被废弃,因此重写代码以使用argparse模块是明智的。但是我找不到任何方法来获取添加到解析器对象的所有命令行参数的所有默认值:

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)

我希望在运行程序时使用 (./app.py -d) 或者没有任何命令行参数 (./app.py) 时获取所有默认值。

Translated:

我想要在运行程序时,使用(./app.py -d)或者没有任何的命令行参数(./app.py),获得所有默认值。


当省略开关时,args对象上设置了默认值。您是否需要访问它们以进行其他操作? - Martijn Pieters
1
所以在你的例子中,当你不使用 -d 运行程序时,args.debug 被设置为 False。你需要知道当你使用 -d 运行程序时默认值是 False 的用例是什么? - Martijn Pieters
你考虑过使用 docopt 吗? - pylang
1
我找到了解决方案,当我运行defaults = vars(parser.parser-args([]))时,我会得到一个包含所有默认值的字典。顺便说一句:当我有很多参数需要区分命令行指定的值和默认值时,我需要它。 - JiriHnidek
5个回答

16

我找到了解决方法:

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([]))

然后您可以比较argsdefaults的值,区分来自命令行的值和默认值。


10

如果您不想解析空输入字符串,则可以在parser对象中使用方法get_default

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)}

感谢您的回答。看起来这也是一个可行的解决方案。 - JiriHnidek
1
我必须使用 parser.get_default('debug') 才能使其正常工作。 - Trevor McCasland

4

稍有些晚了,但这是一个函数(带有额外的单元测试),在某些情况下我使用它来获取默认参数而无需事先解析(如果您有尚未可用的必需参数,则先解析可能很麻烦)。

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)

谢谢,它起作用了。我还需要将默认对象设置为正确的类型:default = action.default;if action.type is not None: default = action.type(default);defaults[action.dest] = default;请注意,布尔标志需要进行none检查。 - Alex Li

1
对于上面的例子:
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. 获取所有值及其默认值的 tuple 格式:

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

访问每个项目的方法:

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

B.dictionary 格式获取值及其默认值

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

并且访问每个键:

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

或者迭代地打印它们:

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

Out[5]: value for debug is: False

1

提供信息,以下是代码,在解析开始时初始化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])
    ...

所以它循环遍历parser._actions列表,收集action.default属性。(一个action是由parser.add_argument方法创建的Action类对象)。它还检查self._defaults。这是由parse.set_defaults方法修改的字典。它可以用于设置与操作直接不相关的默认值。
在解析命令行后,可能会评估名称空间中的默认字符串(使用action.type),将例如default='1'转换为整数1。 argparse中处理默认值并不简单。您的parse_args([])可能是最简单的,前提是解析器可以接受它(即没有任何必需参数)。
我现在不知道optparse如何设置defaults属性。有一个非常重要的方法,optparse.OptionParser.get_default_values

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接