不同的选项集

我有一个名为program.py的程序,我使用argparse来执行参数解析。

我有两种模式我想运行这个二进制文件:1)模拟,它不需要参数2)非模拟,它需要很多参数

我希望程序要么接受

python program --simulation

要么

python program arg1 arg2 arg3 arg4

所有'参数'都是必需的。

我认为这样做的唯一方法是在所有字段中添加'required = False'并手动检查逻辑,但我想知道是否有更优雅的方式。

这是我的代码的减少版本

def get_args():
    parser = argparse.ArgumentParser(description = "program")
    parser.add_argument("arg1", type = bool)
    parser.add_argument("arg2" ,type = str)
    parser.add_argument("arg3", type = int)
    parser.add_argument("arg4", type = str)
    parser.add_argument("--simulation")
    args = parser.parse_args()
    return args

argparse不可能那么聪明。 然而,在你的简单情况下,你可以“帮助”它来选择正确的解析选项:

def get_args(args=sys.argv[1:]):
    parser = argparse.ArgumentParser(description = "program")
    if args and args[0].startswith("--"):
        parser.add_argument("--simulation")
    else:
        parser.add_argument("arg1", type = bool)
        parser.add_argument("arg2" ,type = str)
        parser.add_argument("arg3", type = int)
        parser.add_argument("arg4", type = str)
    args = parser.parse_args(args=args)
    return args

所以print(get_args("--simulation xx".split()))产生:

Namespace(simulation='xx')

因为第一个参数以--开头。 任何其他选项都无法按预期方式执行命令行解析。

print(get_args("True foo 3 bar".split()))产生:

Namespace(arg1=True, arg2='foo', arg3=3, arg4='bar')

忘记4个位置参数中的一个会导致命令行解析失败。

顺便说一句,我已经添加了一个默认参数,如果省略了读取系统参数(就像它在你的代码中那样)。 否则,您可以从文本文件中读取并传递参数标记。 因此,测试更容易,并且可以创建可以使用其他模块的参数调用的模块,而无需通过sys.argv进行破解。


这显然是argparse一个尴尬规范,我怀疑大多数其他POSIX样式解析器。

扫描sys.argv并调整解析器定义是一种可能的方法。

另一种方法是使用2阶段解析器,并使用parse_known_args

import argparse
usage = 'prog [-h] [--simulation] [arg1 arg2 arg3 arg4]'
parser1 = argparse.ArgumentParser(usage=usage)
parser1.add_argument('--simulation', action='store_true')
# or omit the `store_true` if it just takes one argument
# other possible optionals

parser2 = argparse.ArgumentParser()
#parser2.add_argument("arg1", type = bool)  # not a valid type parameter
parser2.add_argument("arg2" )
parser2.add_argument("arg3", type = int)
parser2.add_argument("arg4")
# positionals are required, unless nargs=? or *

args, extras = parser1.parse_known_args()
if not args.simulation:
    args = parser2.parse_args(extras, namespace=args)
elif extras:
    parser1.error('cannot use --simulation with args')
print(args)

可能的运行包括:

1526:~/mypy$ python stack41556997.py -h
usage: prog [-h] [--simulation] [arg1 arg2 arg3 arg4]

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

1526:~/mypy$ python stack41556997.py --simulation
Namespace(simulation=True)

1527:~/mypy$ python stack41556997.py 1 2 3
Namespace(arg2='1', arg3=2, arg4='3', simulation=False)

1527:~/mypy$ python stack41556997.py 1 2 3 --sim
usage: prog [-h] [--simulation] [arg1 arg2 arg3 arg4]
stack41556997.py: error: cannot use --simulation with args

请注意,该帮助不包括这两个集合。 我在自定义用法中包含了一些信息,但没有帮助行的帮助arg# 。 生成一个很好的help信息会随着您的规范而变得尴尬。

我跳过了你的arg1type=bool不是有效的type参数。 使用argparse解析布尔值时请参阅我的解释

我改变了 - --simulation store_true因为你说它没有任何参数。 这是接受True / False的正常方式。

Subparsers通常是接受不同模式论证的最佳工具。 在这种情况下,你可以有一个叫做'simulate'的subparser不需要任何参数,另一个叫'somethingelse'需要4个参数。

我打算建议一个互相--simulation和 - --other选项。 但是, store_true参数在这样的组中不起作用。

=============

子分析器路线:

parser = argparse.ArgumentParser()
sp = parser.add_subparsers(dest='cmd')
sp.add_parser('simulate')
parser2 = sp.add_parser('other')
parser2.add_argument("arg2" )
parser2.add_argument("arg3", type = int)
parser2.add_argument("arg4")
print(parser.parse_args())

测试:

1552:~/mypy$ python stack41556997.py -h
usage: stack41556997.py [-h] {simulate,other} ...

positional arguments:
  {simulate,other}

optional arguments:
  -h, --help        show this help message and exit
1557:~/mypy$ python stack41556997.py simulate
Namespace(cmd='simulate')
1557:~/mypy$ python stack41556997.py other -h
usage: stack41556997.py other [-h] arg2 arg3 arg4

positional arguments:
  arg2
  arg3
  arg4

optional arguments:
  -h, --help  show this help message and exit
1557:~/mypy$ python stack41556997.py other 1 2 3
Namespace(arg2='1', arg3=2, arg4='3', cmd='other')

请注意, arg3 type将输入转换为整数。 其他人留作字符串。 通过这个设置, args.cmd将是args.cmd的名称,与boolean args.simulation属性不完全相同。

==================

标记的参数默认不是必需的。 位置参数是必需的,除非nargs值是'?' 要么 '*'。 您无法为位置提供“必需”参数。

链接地址: http://www.djcxy.com/p/61971.html

上一篇: different sets of options

下一篇: Handling argparse escaped character as option