2012-04-12 109 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的答案可能比我的簡單得多。