2012-04-12 139 views
3

我想使用带参数和位置参数的python-argparse。说我有我的脚本在命令行(这只是一个简单的&愚蠢的例子),这是我到目前为止的代码: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) 

现在,作为您可以看到我总是获得相同的Namespace对象,并且无法区分verbose命令是常规参数还是子分析器参数。 但我需要分开处理这些参数。 什么是简单的方法(用最少的代码工作)来做到这一点?

编辑

我申请了Python STDLIB问题跟踪器内部的问题: http://bugs.python.org/issue15327

+0

子问题:我在哪里提交argparse的问题? – ifischer 2012-04-12 21:02:13

+1

它在标准库中,所以错误转到http://bugs.python.org/。不过,对于功能请求,您应该使用python-list或python-ideas;请参阅http://docs.python.org/devguide/communication.html。 – 2012-04-12 21:09:20

+0

我认为这是一个很好的问题。看起来子分析器应该(可选地)在名称空间内返回一个名称空间,但显然他们不能像那样工作。另外,我有点惊讶地发现'add_subparsers'的dest关键字确实做了一些事情。 (它似乎没有记录在任何地方) – mgilson 2012-04-12 22:26:14

回答

4

你的子分析器的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) 
+0

只要没有太多重载的命令行参数,这个效果就很好。 – mgilson 2012-04-12 22:28:17

+0

我向add_argument添加了metavar-param,以便argparse-help不打印CMD1_VERBOSE: cmd1_parser.add_argument(' - verbose',action ='store_true',dest ='cmd1_verbose',metavar ='VERBOSE' )' – ifischer 2012-07-11 13:36:01

3

这里有一些我一起入侵的东西。我几乎可以保证它没有缺陷,但是它在这个简单的测试中起作用。

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的答案可能比我的简单得多。