argparse 中的交叉参数验证
Cross-argument validation in argparse
我正在寻找一种 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
参数相关联,因为界面无法告诉您 哪个 值需要在这里改变。每个值都有效,但不能组合使用。
我们可以通过 post 处理 args
命名空间来做到这一点,但我正在寻找一个会导致 parser.parse_args()
调用失败的解决方案,即我们实际上失败了在参数解析期间,而不是之后。
解析后检查值是最简单的。您甚至可以使用 parser.error('...')
以标准 argparse
格式生成错误消息。
argparse
独立处理每个参数,并尝试以不关心顺序的方式进行处理(positionals
除外)。每个输入值都由相应的 Action
对象(其 __call__
方法)添加到 args
命名空间。默认的 store
操作仅使用 setattr(args, dest, value)
; store_true
做 setattr(args, dest, True)
.
互斥组的处理方式是保持 seen_actions
的 set
,并对照组自己的操作列表进行检查。我探索了概括这些组以允许其他逻辑操作组合。尽管变得如此复杂(尤其是在显示 usage
时),但我没有设想对值和发生率进行测试。
可以编写自定义 Action
classes 来检查 co-occurrence,但这会变得更加复杂。
我们可以给 with-shoes
一个动作 class 检查 args.animal
属性的值,如果该值为 snake
则引发错误。但是如果用户先提供 with-shoes
选项呢?我们必须给 animal
一个检查 args.with_shoes
值的自定义 class,如果是 True
则引发错误,等等。所以 shoes
有了解 animals
和 animals
必须了解 shoes
。解析后测试可以让你把逻辑放在一个地方。
使用像 argparse
这样的解析器的一大优势是它会为您生成用法、帮助和错误消息。但是像这样的验证逻辑很难自动表达。事实上,相对简单的 mutually-exclusive 逻辑的使用格式很脆弱,很容易被破坏。
较早前尝试回答此类问题:
我正在寻找一种 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
参数相关联,因为界面无法告诉您 哪个 值需要在这里改变。每个值都有效,但不能组合使用。
我们可以通过 post 处理 args
命名空间来做到这一点,但我正在寻找一个会导致 parser.parse_args()
调用失败的解决方案,即我们实际上失败了在参数解析期间,而不是之后。
解析后检查值是最简单的。您甚至可以使用 parser.error('...')
以标准 argparse
格式生成错误消息。
argparse
独立处理每个参数,并尝试以不关心顺序的方式进行处理(positionals
除外)。每个输入值都由相应的 Action
对象(其 __call__
方法)添加到 args
命名空间。默认的 store
操作仅使用 setattr(args, dest, value)
; store_true
做 setattr(args, dest, True)
.
互斥组的处理方式是保持 seen_actions
的 set
,并对照组自己的操作列表进行检查。我探索了概括这些组以允许其他逻辑操作组合。尽管变得如此复杂(尤其是在显示 usage
时),但我没有设想对值和发生率进行测试。
可以编写自定义 Action
classes 来检查 co-occurrence,但这会变得更加复杂。
我们可以给 with-shoes
一个动作 class 检查 args.animal
属性的值,如果该值为 snake
则引发错误。但是如果用户先提供 with-shoes
选项呢?我们必须给 animal
一个检查 args.with_shoes
值的自定义 class,如果是 True
则引发错误,等等。所以 shoes
有了解 animals
和 animals
必须了解 shoes
。解析后测试可以让你把逻辑放在一个地方。
使用像 argparse
这样的解析器的一大优势是它会为您生成用法、帮助和错误消息。但是像这样的验证逻辑很难自动表达。事实上,相对简单的 mutually-exclusive 逻辑的使用格式很脆弱,很容易被破坏。
较早前尝试回答此类问题: