如何确定是否在命令行上实际指定了argparse参数?

2024-05-17 18:57:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用arparse使用命令行中指定的值更新配置dict。因为我只想更新配置中的值,在命令行中明确提到了一个值。

因此,我试图通过检查每个操作(如果getattr(args, action.dest) == action.default)或转换参数类型的相等性来标识未指定的参数。然后我更新dict中的所有值,这是错误的。

但如果我在命令行上显式指定一个参数(与默认参数相同),这当然会失败。有没有可能用argparser来识别这些显式提到的参数,或者我有没有 在sys.argv中手动识别它们?

谢谢!

编辑:

让我的意图更清楚。我有如下论点:

parser.add_argument('--test', default='meaningful_default')

像这样的配置

config = { 'test' : 'nondefault_val'}

现在我只想用显式指定的参数更新配置。只要我不指定像prog.py --test meaningful_default这样的东西来再次用一个恰好也是默认值的值更新我的配置,就可以将args属性与默认值进行比较


Tags: 命令行testdefault类型参数错误argsaction
3条回答

解析时,parser维护一个seen_actionsset对象(在_parse_known_args方法中)。在解析结束时,它会根据所需的参数(带有required=True的参数)检查此集合,并可能发出错误。变体也用于互斥组。

但此变量在该函数之外不可用。因此,如果没有某种“钩子”可以让您在parse_args操作中应用自己的测试,那么最好的选择就是测试默认值。或者你可以看看sys.argv[1:]

默认的defaultNone。这样做很好,因为您的用户无法提供此值。也就是说,没有字符串可以转换成None(至少在任何正常的type方法中都没有)。

parser.add_argument('--foo') # default=None
...
if args.foo is None:
    # clearly foo has not been specified.
    args.foo = 'the real default'
else:
    # foo was specified
    pass

如果您希望使用argparse并能够指定默认值,那么有一个使用两个解析器的简单解决方案。

I.定义主解析器并使用适当的默认值分析所有参数:

parser = argparse.ArgumentParser()
parser.add_argument('--test1', default='meaningful_default1')
parser.add_argument('--test2', default='meaningful_default2')
...
args, unparsed = parser.parse_known_args()

二。用argument_default=argparse.SUPPRESS定义一个aux解析器以排除未指定的参数。添加主分析器中的所有参数,但不使用任何默认值:

aux_parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
for arg in vars(args): aux_parser.add_argument('--'+arg)
cli_args, _ = aux_parser.parse_known_args()

这不是一个非常优雅的解决方案,但是可以很好地与argparse及其所有优点配合使用。

您可以使用自定义操作来判断参数值是默认值还是在命令行上设置的:

import argparse

class FooAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, values)
        setattr(namespace, self.dest+'_nondefault', True)

parser = argparse.ArgumentParser()
parser.add_argument('--test0', default='meaningful_default', action=FooAction)
parser.add_argument('--test1', default='meaningful_default', action=FooAction)

args = parser.parse_args('--test0 2'.split())

if hasattr(args, 'test0_nondefault'):
    print('argument test0 set on command line')
else:
    print('default value of test0 is used')

if hasattr(args, 'test1_nondefault'):
    print('argument test1 set on command line')
else:
    print('default value of test1 is used')

相关问题 更多 >