如何显示可选和条件参数的自定义错误消息

How to display custom error message for optional and conditional argument

我正在尝试在 Python 脚本中实现一个命令行参数,它既是有条件的又是可选的。因此,有效用法如下所示,其中“-a”是可选的,“-b”是可选的,但仅在指定“-a”时才有效。

[-a argumentA [-b argumentB]]

我有使用 argparse 执行此操作的解决方案,但我无法获得帮助和错误文本来执行我想要的操作。这是我的解决方案:

import argparse

parser = argparse.ArgumentParser()

parser.add_argument("-a", "--AAA", dest="aaa_arg", help="this is the 'a' argument")

namespace, extra = parser.parse_known_args()
if namespace.aaa_arg != None:
    parser.add_argument("-b", "--BBB", dest="bbb_arg", help="only use 'b' when 'a' is used")

myArgs = parser.parse_args()

if myArgs.aaa_arg != None:
    print("AAA: " + myArgs.aaa_arg)
    if myArgs.bbb_arg != None:
        print("BBB: " + myArgs.bbb_arg)

命令行上各种参数的输出为:

>py test.py

>py test.py -a something
AAA: something

>py test.py -a something -b somethingElse
AAA: something
BBB: somethingElse

>py test.py -b somethingElse
usage: test.py [-h] [-a AAA_ARG]
test.py: error: unrecognized arguments: -b somethingElse

>py test.py -h
usage: test.py [-h] [-a AAA_ARG]

optional arguments:
  -h, --help                   show this help message and exit
  -a AAA_ARG, --AAA AAA_ARG    this is the 'a' argument

>

问题是被告知“-b”是一个有效参数的用户会被“-b somethingElse”无法识别的错误消息所迷惑。如果该用户随后显示帮助,他们将看不到列出的“-b”。

修复帮助非常简单。下面的第二个版本在 ArgumentParser 中使用 conflict_handler 以允许自定义帮助消息。

import argparse

parser = argparse.ArgumentParser(conflict_handler="resolve")
parser.add_argument("-h", "--help", action="store_true", dest="display_help")

parser.add_argument("-a", "--AAA", dest="aaa_arg", help="this is the 'a' argument")

namespace, extra = parser.parse_known_args()
if namespace.aaa_arg != None:
    parser.add_argument("-b", "--BBB", dest="bbb_arg", help="only use 'b' when 'a' is used")

myArgs = parser.parse_args()

if myArgs.display_help:
    print('''usage: test2.py [-h] [-a AAA_ARG [-b BBB_ARG]]

optional arguments:
  -h, --help                   show this help message and exit
  -a AAA_ARG, --AAA AAA_ARG    this is the 'a' argument
  -b BBB_ARG, --BBB BBB_ARG    only use 'b' when 'a' is used''')
else:    
    if myArgs.aaa_arg != None:
        print("AAA: " + myArgs.aaa_arg)
        if myArgs.bbb_arg != None:
            print("BBB: " + myArgs.bbb_arg)

正如您在下面的输出中看到的,帮助消息将“-b”列为有效参数;但是,错误消息仍然指出“-b somethingElse”无法识别。

>py test2.py

>py test2.py -a something
AAA: something

>py test2.py -a something -b somethingElse
AAA: something
BBB: somethingElse

>py test2.py -b somethingElse
usage: test2.py [-h] [-a AAA_ARG]
test2.py: error: unrecognized arguments: -b somethingElse

>py test2.py -h
usage: test2.py [-h] [-a AAA_ARG [-b BBB_ARG]]

optional arguments:
  -h, --help                   show this help message and exit
  -a AAA_ARG, --AAA AAA_ARG    this is the 'a' argument
  -b BBB_ARG, --BBB BBB_ARG    only use 'b' when 'a' is used

>

我真正想要的是如下所示的输出(此输出是手动创建的示例,而不是 Python):

>py test3.py

>py test3.py -a something
AAA: something

>py test3.py -a something -b somethingElse
AAA: something
BBB: somethingElse

>py test3.py -b somethingElse
usage: test2.py [-h] [-a AAA_ARG [-b BBB_ARG]]
test2.py: only use 'b' when 'a' is used

>py test3.py -h
usage: test2.py [-h] [-a AAA_ARG [-b BBB_ARG]]

optional arguments:
  -h, --help                   show this help message and exit
  -a AAA_ARG, --AAA AAA_ARG    this is the 'a' argument
  -b BBB_ARG, --BBB BBB_ARG    only use 'b' when 'a' is used

>

有没有办法自定义“-b”选项的错误消息?

更新:

根据@hpaulj 的建议,我将解析和条件检查分开了。该解决方案将“-a”和“-b”参数都添加到解析器,然后检查条件并使用自定义消息设置错误。

将自定义用法消息添加到 ArgumentParser 并通过参数上的元变量属性调整帮助显示的参数名称与帮助消息中的 uasge 语句和参数描述相匹配。 最终结果比我开始时的更简单:不需要解析两次,也不需要自定义帮助消息。

import argparse

parser = argparse.ArgumentParser(usage="%(prog)s [-h] [-a argA [-b argB]]")

parser.add_argument("-a", "--AAA", metavar="argA", dest="aaa_arg", help="this is the 'a' argument")
parser.add_argument("-b", "--BBB", metavar="argB", dest="bbb_arg", help="only use 'b' when 'a' is used")

myArgs = parser.parse_args()

if myArgs.aaa_arg == None and myArgs.bbb_arg != None:
    parser.error("only use 'b' when 'a' is used")

if myArgs.aaa_arg != None:
    print("AAA: " + myArgs.aaa_arg)
    if myArgs.bbb_arg != None:
        print("BBB: " + myArgs.bbb_arg)




>py test2.py

>py test2.py -a something
AAA: something

>py test2.py -a something -b somethingElse
AAA: something
BBB: somethingElse

>py test2.py -b somethingElse
usage: test2.py [-h] [-a argA [-b argB]]
test2.py: error: only use 'b' when 'a' is used

>py test2.py -h
usage: test2.py [-h] [-a argA [-b argB]]

optional arguments:
  -h, --help           show this help message and exit
  -a argA, --AAA argA  this is the 'a' argument
  -b argB, --BBB argB  only use 'b' when 'a' is used

>

第一次尝试

The issue is that a user who has been told that “-b” is a valid argument will be confused by the error message that says “-b somethingElse” is unrecognized. If that user then displays the help, they will not see “-b” listed.

第一个 parse_known_args() 处理,或者说忽略 -b。但是它作用于-h。第二个 parse_args() 是抱怨无法识别的 -b

ArgumentParser(add_help=False) 创建一个没有自动帮助的解析器;那是您 resolve 的替代品。您可以在第一个 parse_know_args.

之后添加自定义或标准帮助

另一件需要考虑的事情是自定义 usage 字符串。

如果您不想让它抱怨 -b,请跳过 parse_args 或再次使用 parse_known_args

parser.error('custom message') 可用于显示自定义错误。

argparse 没有提供一种使一个参数以另一个参数为条件的便捷方法。我们通常建议在解析后进行此类测试,而不是在解析时尝试全部执行(或使用 2 次解析调用)。请记住,argparse 尝试以任何顺序处理 optionals-a foo -b bar-b bar -a foo 相同。