Python argparse - 必填参数 - 位置参数或可选参数

5
我希望用户能够通过位置参数或可选参数向 'argparse' 传递必填的参数。
例如,以下两种形式都是有效的:
my_prog arg
my_prog -m arg

我看到了Argparse optional positional arguments?的建议,但这样做会使两个形式都可选。我希望其中一个是必需的。 当然,我可以在解析后添加手动检查,以确保它们中至少有一个已设置。但我有一种直觉,认为一定有更好的解决办法。 (即使使用我的手动方法,“帮助”部分也将显示两个参数都是可选的)
1个回答

8
“互斥组”机制可以使用“required”参数。它还可以与一个“?”位置参数和可选参数(标志参数)一起使用。(多个“?”位置参数没有意义)
至于“help”显示,有两个默认组,“positonal”和“optional”。因此,即使将“optional”(标记)设置为“required”,默认情况下也会在“optional”组中显示。“usage”行更好地指导参数是否必需。如果您不喜欢帮助部分中的组标签,请定义自己的参数组。
In [146]: import argparse
In [147]: parser = argparse.ArgumentParser()
In [148]: gp = parser.add_mutually_exclusive_group(required=True)
In [149]: gp.add_argument('pos', nargs='?', default='foo');
In [150]: gp.add_argument('-f','--foo', default='bar');

In [151]: parser.parse_args('arg'.split())
Out[151]: Namespace(foo='bar', pos='arg')

In [152]: parser.parse_args('-f arg'.split())
Out[152]: Namespace(foo='arg', pos='foo')

In [153]: parser.parse_args('arg -f arg'.split())
usage: ipython3 [-h] [-f FOO] [pos]
ipython3: error: argument -f/--foo: not allowed with argument pos

In [154]: parser.parse_args(''.split())
usage: ipython3 [-h] [-f FOO] [pos]
ipython3: error: one of the arguments pos -f/--foo is required


In [155]: parser.parse_args('-h'.split())
usage: ipython3 [-h] [-f FOO] [pos]

positional arguments:
  pos

optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO

哎呀,使用方法没有显示-fpos在互斥组中。有时候这种usage格式很脆弱。

改变参数定义的顺序可以得到更好的使用方式。

In [156]: parser = argparse.ArgumentParser()
In [157]: gp = parser.add_mutually_exclusive_group(required=True)
In [158]: gp.add_argument('-f','--foo', default='bar');
In [159]: gp.add_argument('pos', nargs='?', default='foo');
In [160]: 
In [160]: parser.parse_args('-h'.split())
usage: ipython3 [-h] (-f FOO | pos)

positional arguments:
  pos

optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO

使用用户定义的参数组:

In [165]: parser = argparse.ArgumentParser()
In [166]: gp = parser.add_argument_group('Mutually exclusive')
In [167]: gpm = gp.add_mutually_exclusive_group(required=True)
In [168]: gpm.add_argument('-f','--foo', default='bar');
In [169]: gpm.add_argument('pos', nargs='?', default='foo');
In [170]: 
In [170]: parser.parse_args('-h'.split())
usage: ipython3 [-h] (-f FOO | pos)

optional arguments:
  -h, --help         show this help message and exit

Mutually exclusive:
  -f FOO, --foo FOO
  pos

这是一条例外规则:argument_groups和mutually_exclusive_groups不适合嵌套使用。

m-x-group不是必须的,使用时可以用[]代替。

usage: ipython3 [-h] [-f FOO | pos]

太好了。只有一个注意事项:这些组定义必须在所有其他常规参数之后,否则在帮助中不会显示漂亮的 (-f FOO | pos) - Zvika
是的,有两件事影响着“使用情况”。位置参数会显示在可选参数之后,只有当其参数匹配该顺序时,该组才会出现。纠正这种脆弱性需要对使用情况格式化程序进行重大改写。 - hpaulj

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