Argparse:指定可选参数时忽略多个位置参数

19 python argparse

我试图让argparse忽略这样一个事实,即当-l指定了一个可选的参数()时,不应该评估两个通常需要的位置参数.

基本上我试图复制--help的行为:当你指定-h时,忽略所有缺少的必需参数.

示例代码:

parser = argparse.ArgumentParser(description="Foo bar baz")
parser.add_argument('arg1', help='arg1 is a positional argument that does this')
parser.add_argument('arg2', help='arg2 is a positional argument that does this')
parser.add_argument('-l', '--list', dest='list', help='this is an optional argument that prints stuff')

options, args = parser.parse_args()

if options.list:
   print "I list stuff"
Run Code Online (Sandbox Code Playgroud)

当然,如果我现在运行它,我得到:

error: too few arguments
Run Code Online (Sandbox Code Playgroud)

我尝试了不同的东西nargs='?',但是无法正常工作.

这个问题非常相似,但没有得到回答.

Sve*_*ach 8

不幸的是,argparse对此不够灵活.您可以做的最好的事情是制作arg1arg2选择使用nargs="?"并检查自己是否在需要时给出.

内部help操作通过打印帮助消息并在命令行上遇到-h或立即退出程序来实现--help.你可以自己写一个类似的动作,比如

class MyAction(argparse.Action):
    def __call__(self, parser, values, namespace, option_string):
        print "Whatever"
        parser.exit()
Run Code Online (Sandbox Code Playgroud)

(警告:未经测试的代码!)

不过,后一种方法有明显的缺点.帮助信息将无条件地显示arg1arg2作为强制性参数.解析命令行只会在遇到-l--list忽略任何进一步的参数时停止.这种行为是完全可以接受的--help,但对于其他选项来说则不太理想.


Mat*_*hew 6

我遇到了这个问题并决定使用子命令.子命令可能有点过分,但是如果你发现你的程序在许多实例中没有使用某些位置参数(就像我一样),那么子命令可能是一个很好的解决方案.

对于您给出的示例,我将使用以下内容:

parser = argparse.ArgumentParser(description="Foo bar baz")
subparsers = parser.add_subparsers(description='available subcommands')

parser_main = subparsers.add_parser('<main_command_name>')
parser_main.add_argument('arg1', help='arg1 is a positional argument that does this')
parser_main.add_argument('arg2', help='arg2 is a positional argument that does this')

parser_list = subparsers.add_parser('list', help='this is a subcommand that prints stuff')

options, args = parser.parse_args()
Run Code Online (Sandbox Code Playgroud)

我遗漏了一些你可能想要包含的细节(比如set_defaults(func=list)),这些细节在argparse文档中提到过.


Mad*_*ist 5

到目前为止,我能找到的最简洁的方法是将解析分为两个阶段。首先检查-l/--list

parser = argparse.ArgumentParser(description="Foo bar baz")
parser.add_argument('-l', '--list', dest='list', action='store_true',
                    help='this is an optional argument that prints stuff')

options, remainder = parser.parse_known_args()
Run Code Online (Sandbox Code Playgroud)

现在,由于您使用了parse_known_args,所以到目前为止您不会收到错误,并且您可以决定如何处理参数remainder

if options.list:
    print "I list stuff"
else:
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument('arg1', help='arg1 is a positional argument that does this')
    parser.add_argument('arg2', help='arg2 is a positional argument that does this')
    options = parser.parse_args(remainder)
Run Code Online (Sandbox Code Playgroud)

您可能需要在第一个解析器中设置使用选项以使帮助字符串更好一些。