【问题标题】:Cross-argument validation in argparseargparse 中的交叉参数验证
【发布时间】:2018-08-06 14:25:15
【问题描述】:

当参数的验证在逻辑上取决于从其他参数解析的值时,我正在寻找一种 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

在这里添加mutually exclusive group 似乎没有帮助,因为其他组合都可以:

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() 调用失败的解决方案,即我们实际上在期间 参数解析失败,而不是之后。

【问题讨论】:

  • 不直接回答你的问题,但我更喜欢使用 Click 因为它更适合这种事情:stackoverflow.com/a/44349292/7311767
  • 谢谢,但我不喜欢使用 click,因为我不喜欢我的参数解析代码在函数上方的一堆装饰器中。它使 CLI 难以测试并且代码难以阅读。寻找argparse 解决方案。

标签: python argparse


【解决方案1】:

解析后检查值是最简单的。您甚至可以使用parser.error('...') 生成标准argparse 格式的错误消息。

argparse 独立处理每个参数,并尝试以不关心顺序的方式这样做(positionals 除外)。每个输入值通过相应的Action 对象(其__call__ 方法)添加到args 命名空间。默认的store 操作只使用setattr(args, dest, value)store_truesetattr(args, dest, True)

通过保留setseen_actions 来处理互斥组,并根据组自己的操作列表检查该组。我已经探索了泛化这些组以允许其他逻辑组合的操作。如此复杂(尤其是在显示 usage 时),我并没有设想对值和发生率进行测试。

可以编写自定义Action 类来检查共现,但这会变得更加复杂。

我们可以给with-shoes 一个Action 类,它检查args.animal 属性的值,如果该值是snake,则引发错误。但是如果用户首先提供with-shoes 选项呢?我们必须给animal 一个自定义类来检查args.with_shoes 的值,如果是True 等则引发错误。所以shoes 必须知道animalsanimals 必须知道了解shoes。解析后测试可以让你把逻辑放在一个地方。

使用像argparse 这样的解析器的一大优势是它会为您生成用法、帮助和错误消息。但是像这样的验证逻辑很难自动表达。事实上,相对简单的互斥逻辑的使用格式很脆弱,很容易被破坏。

回答此类问题的较早尝试:

Parameter dependencies in Python - can't make it work

【讨论】:

    猜你喜欢
    • 2012-08-21
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    • 2019-08-22
    • 2023-03-10
    • 2018-03-09
    • 2018-06-13
    相关资源
    最近更新 更多