argparse -- 可选参数需要 2 个值或 none

argparse -- requiring either 2 values or none for an optional argument

我正在尝试为脚本创建一个可选参数,该参数可以不带任何值或 2 个值,仅此而已。你能用 argparse 完成这个吗?

# desired output:
# ./script.py -a --> works
# ./script.py -a val1 --> error
# ./script.py -a val1 val2 --> works


版本 1 -- 接受 0 或 1 个值:

parser = argparse.ArgumentParser()
parser.add_argument("-a", "--action", nargs="?", const=True, action="store", help="do some action")
args = parser.parse_args()

# output:
# ./script.py -a --> works
# ./script.py -a val1 --> works
# ./script.py -a val1 val2 --> error


版本 2 - 正好接受 2 个值:

parser = argparse.ArgumentParser()
parser.add_argument("-a", "--action", nargs=2, action="store", help="do some action")
args = parser.parse_args()

# output:
# ./script.py -a --> error
# ./script.py -a val1 --> error
# ./script.py -a val1 val2 --> works


如何组合这 2 个不同的版本,以便脚本接受 0 或 2 个参数值,但在只有 1 个值时拒绝它?

你自己处理那个案子:

parser.add_argument("-a", "--action", nargs='*', action="store", help="do some action")
args = parser.parse_args()

if args.action is not None:
    if len(args.action) not in (0, 2):
        parser.error('Specify no or two actions')

    # action was specified but either there were two actions or no action
else:
    # action was not specified

当然,在这种情况下您应该更新帮助文本,以便用户有机会在 运行 进入错误之前知道这一点。

您必须在此处进行自己的错误检查。接受 0 个或更多值,拒绝 0 或 2 以外的任何值:

parser = argparse.ArgumentParser()
parser.add_argument("-a", "--action", nargs='*', action="store", help="do some action")
args = parser.parse_args()

if args.action is not None and len(args.action) not in (0, 2):
    parser.error('Either give no values for action, or two, not {}.'.format(len(args.action)))

请注意,当未使用 -a 开关时,args.action 设置为 None

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument("-a", "--action", nargs='*', action="store", help="do some action")
_StoreAction(option_strings=['-a', '--action'], dest='action', nargs='*', const=None, default=None, type=None, choices=None, help='do some action', metavar=None)
>>> args = parser.parse_args([])
>>> args.action is None
True
>>> args = parser.parse_args(['-a'])
>>> args.action
[]

所需参数如何:parser.add_argument("-a", "--action", nargs=2, action="store", help="do some action", required=False)

让您的选项采用单个可选的逗号分隔字符串。您将使用自定义类型将该字符串转换为列表并验证它是否恰好包含两项。

def pair(value):
    rv = value.split(',')
    if len(rv) != 2:
        raise argparse.ArgumentParser()
    return rv

parser.add_argument("-a", "--action", nargs='?',
                    type=pair, metavar='val1,val2',
                    help="do some action")
print parser.parse_args()

然后你会像

一样使用它
$ ./script.py -a
Namespace(action=None)
$ ./script.py -a val1,val2
Namespace(action=['val1','val2'])
$ ./script.py -a val1
usage: tmp.py [-h] [-a [ACTION]]
script.py: error: argument -a/--action: invalid pair value: 'val1'
$ ./script.py -a val1,val2,val3
usage: tmp.py [-h] [-a [ACTION]]
script.py: error: argument -a/--action: invalid pair value: 'val1,val2,val3'

您可以调整 pair 的定义以使用不同的分隔符和 return 列表以外的内容(例如元组)。

metavar 更好地表明 action 的参数是一对值,而不仅仅是一个值。

$ ./script.py -h
usage: script.py [-h] [-a [val1,val2]]

optional arguments:
  -h, --help            show this help message and exit
  -a [val1,val2], --action [val1,val2]
                        do some action