argparse中的交叉参数验证

16

我希望找到一种Pythonic的方式,在需要从其他参数解析出值时逻辑地验证参数。

这里有一个简单的例子:

parser.add_argument(
    '--animal', 
    choices=['raccoon', 'giraffe', 'snake'], 
    default='raccoon',
)
parser.add_argument(
    '--with-shoes', 
    action='store_true',
)

在这种情况下,解析此命令应该会导致错误:

my_script.py --animal snake --with-shoes

似乎添加一个互斥组在这里并没有帮助,因为其他组合是可以的:

my_script.py --animal raccoon --with-shoes
my_script.py --animal raccoon
my_script.py --animal snake
my_script.py --animal giraffe --with-shoes
my_script.py --animal giraffe

最好不要将验证错误与--animal参数或--with-shoes参数绑定在一起,因为界面无法告诉您更改哪个值。每个值都是有效的,但不能组合使用。

我们可以通过对args名称空间进行后处理来做到这一点,但我正在寻找一种解决方案,可以导致parser.parse_args()调用失败,即我们实际上在参数解析期间失败,而不是之后。


1
虽然并没有直接回答你的问题,但我更喜欢使用Click,因为它更适合这种情况:https://dev59.com/9VcP5IYBdhLWcg3wiqZr#44349292 - Stephen Rauch
3
谢谢,但我更喜欢不使用click,因为我不喜欢我的参数解析代码在函数上面一堆装饰器中。这使得CLI难以测试,代码难以阅读。我正在寻找一个argparse的解决方案。 - wim
1个回答

9
在解析后检查值是最简单的。您甚至可以使用parser.error('...')以标准的argparse格式生成错误消息。 argparse独立处理每个参数,并尝试以不关心顺序的方式进行处理(除了positionals)。每个输入值都由相应的Action对象(其__call__方法)添加到args命名空间中。默认的store操作只是使用setattr(args, dest, value)store_true则执行setattr(args, dest, True)
互斥组通过保留seen_actionsset并将其与组自己的Actions列表进行检查来处理。我已经探索了将组通用化以允许其他逻辑操作的操作。尽管这变得非常复杂(特别是在显示usage时),但我没有想象过还要测试值以及发生情况。
可以编写自定义的Action类,以检查共同出现,但那会变得更加复杂。
我们可以为with-shoes提供一个Action类,检查args.animal属性的值,并在该值为snake时引发错误。但是如果用户首先提供了with-shoes选项呢?我们必须为animal提供一个自定义类,检查args.with_shoes的值,并在其为True时引发错误等等。因此,shoes必须知道animalsanimals必须知道shoes。解析后进行测试可以将逻辑放在一个地方。

使用像argparse这样的解析器的一个重要优点是它可以为您生成用法、帮助和错误消息。但是像这样的验证逻辑很难自动表达。就目前而言,相对简单的互斥逻辑的用法格式很脆弱,很容易破坏。

早期尝试回答这种问题的一个例子:

Python中的参数依赖性 - 无法使其工作


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