Argparse:如何区分解析器和子解析器的参数

4

我希望使用python-argparse来处理参数和位置参数。比如说,我有一个在命令行上运行的脚本(只是一个简单的例子),这是目前我的代码:

#!/usr/bin/env python
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--verbose', action='store_true')
subparsers = parser.add_subparsers(help='command', dest='command')
cmd1_parser = subparsers.add_parser('command1')
cmd1_parser.add_argument('--verbose', action='store_true')

args = parser.parse_args()

print args

现在我这样调用脚本:
~ $ myscript --verbose command1 --verbose
Namespace(command='command1', verbose=True)

~ $ myscript command1 --verbose
Namespace(command='command1', verbose=True)

~ $ myscript --verbose command1
Namespace(command='command1', verbose=True)

现在你可以看到,我总是得到相同的命名空间对象,并且无法区分详细命令是常规参数还是子解析器参数。但我需要将这些参数分别处理。有没有一种简单的方法(代码最少)来做到这一点?
编辑: 我在Python stdlib问题跟踪器中提交了一个问题:http://bugs.python.org/issue15327

子问题:我在哪里提交argparse的问题? - Wolkenarchitekt
1
它在标准库中,所以错误应提交到http://bugs.python.org/。但对于功能请求,您应该使用python-list或python-ideas;请参见http://docs.python.org/devguide/communication.html。 - Petr Viktorin
我认为这是一个很好的问题。似乎子解析器应该(可选地)返回命名空间中的命名空间,但显然它们不是这样工作的。此外,我有点惊讶于add_subparsers中的dest关键字实际上会起作用。(它似乎没有在任何地方记录) - mgilson
2个回答

5
将您的子解析器的add_argument调用更改为以下内容:
cmd1_parser.add_argument('--verbose', action='store_true', dest='cmd1_verbose')

这将导致你的第一个例子返回:
~ $ myscript --verbose command1 --verbose
Namespace(cmd1_verbose=True, command='command1', verbose=True)

只要命令行参数不太多重载,这个功能就可以很好地工作。 - mgilson
我在add_argument中添加了一个metavar-param,以便argparse-help不打印CMD1_VERBOSE: cmd1_parser.add_argument('--verbose', action='store_true', dest='cmd1_verbose', metavar='VERBOSE') - Wolkenarchitekt

4

这是我草率地拼凑出来的一些东西。我几乎可以保证它不是没有 bug 的,但在这个简单的测试中它起作用了。

import argparse

class _Action(object):
    def __init__(self,master):
        self.master=master
    def add_parser(self,name,**kwargs):
        self.master.subparsers[name]=subParserEnabler()
        return self.master.subparsers[name]

class subParserEnabler(argparse.ArgumentParser):
    def __init__(self,*args,**kwargs):
        self.subparsers={}
        argparse.ArgumentParser.__init__(self,*args,**kwargs)

    def add_subparsers(self,**kwargs):
        return _Action(self)

    def parse_args(self,args,**kwargs):
        args=list(args)
        for k in self.subparsers.keys():
            if k in args:
                break
        try: 
            i=args.index(k)
            output=argparse.ArgumentParser.parse_args(self,args[:i],**kwargs)
            o1=argparse.Namespace()
            setattr(output,k,o1)
            self.subparsers[k].parse_args(args[i+1:],namespace=o1)
        except:
            output=argparse.ArgumentParser.parse_args(self,args,**kwargs)
        return output

parser = subParserEnabler()
parser.add_argument('--verbose', action='store_true')
subparsers = parser.add_subparsers(help='command',dest='command')
cmd1_parser = subparsers.add_parser('command1')
cmd1_parser.add_argument('--verbose', action='store_false')

args = parser.parse_args("--verbose command1 --verbose".split())
print args

它仍然缺少别名,帮助格式可能是错误的......但至少它提供了我想要的输出。最终,John Gaines Jr的回答可能比我的简单得多。


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