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

27 投票
6 回答
11837 浏览
提问于 2025-04-17 02:40

我正在尝试让 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"

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

error: too few arguments

我尝试了不同的方法,比如 nargs='?',但没有找到有效的解决方案。

这个问题也很相似,但没有得到回答。

6 个回答

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()

现在,由于你使用了 parse_known_args,到这里为止不会出现错误,你可以决定如何处理剩下的参数:

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)

你可能想在第一个解析器中设置使用说明选项,这样帮助信息看起来会更好一些。

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()

我省略了一些你可能想要包含的细节(比如 set_defaults(func=list)),这些在argparse 文档中有提到。

9

很遗憾,argparse 的灵活性不够,不能完全满足这个需求。你能做的最好的办法就是把 arg1arg2 设置为可选参数,使用 nargs="?",然后自己检查这些参数是否被提供。

内部的 help 功能是通过在命令行中遇到 -h--help 时,立即打印帮助信息并退出程序来实现的。你可以自己写一个类似的功能,比如:

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

(警告:这段代码没有经过测试!)

不过,这种做法确实有一些缺点。帮助信息会毫无条件地显示 arg1arg2 是必填参数。而且,当命令行遇到 -l--list 时,解析过程会直接停止,忽略后面的任何参数。这种行为对于 --help 来说是可以接受的,但对于其他选项来说就不太理想了。

撰写回答