Argparse set_defaults用于Python 2.7.6以后失效的子解析器



我有一个使用argparse的应用程序,它被最新版本的Python破坏了。我不能再修改子命令的默认值了。

我的应用程序有各种模块和可选的GUI。GUI通过子命令调用模块,并且有一个ini文件可以更改参数的默认值。

GUI创建了解析器和子解析器,并按照GUI用户的设置传递参数。ini文件中的选项可以覆盖子解析器中的默认值。

这在2.7.6中可以工作,但由于argparse的明显变化,在后来的版本中被打破了。

import argparse
# create the top-level parser
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('--foo', action='store_true', dest='_foo')
subparsers = parser.add_subparsers(help='sub-command help')
# create the parser for the "a" command
parser_a = subparsers.add_parser('a', help='a help')
parser_a.add_argument('--bar', type=int, default=0, dest='_bar')
#use ini file to alter default 
d_ini = {'_bar': '1'}
parser.set_defaults(**d_ini)
# parse some argument lists
print parser.parse_args(['a'])

在python 2.7.6中,它会按照预期打印:

名称空间(_bar = 1, _foo = False)

但是在以后的版本中,例如。2.7.10打印

名称空间(_bar = 0, _foo = False)

我使用argparse错误,因为如果这是一个python错误,它已经持续了几个版本了吗?

我需要在添加子解析器默认值之前处理ini文件吗?这将比我目前的方法更麻烦,因为它需要对每个参数单独执行,而且有很多。ArgumentParser的python文档。set_defaults明确地声明"在使用多个解析器时,解析器级别的默认值可能特别有用",所以如果这个功能被破坏了,那就令人惊讶了。

在这种情况下,必须将解析器默认值应用于感兴趣的子解析器。也就是说,在上面的代码中,您应该有:

# set defaults on parser_a
parser_a.set_defaults(**d_ini)

parser上设置默认值不会在子解析器上设置默认值。相反,它为顶级(全局)参数设置默认值。为什么?这样,程序就有可能采用一个选项--bar,并且对于多个子命令a, b, c也都采用不同默认值的选项--bar

前一种行为,在2.7.6中,也出现在3.3中,应该被认为是一个bug。

最新更新