2013-04-03 11 views
7

I引数の異なるセットを有し、二つのサブパーサを定義する次のテストコードargparseと別の名前空間にサブパーサー引数を入れるにはどうすればいいですか?

import argparse 
parser = argparse.ArgumentParser() 
parser.add_argument("--verbose", default = 0, type=int) 

subparsers = parser.add_subparsers(dest = "parser_name") 

parser_lan = subparsers.add_parser('car') 
parser_lan.add_argument("--boo") 
parser_lan.add_argument("--foo") 

parser_serial = subparsers.add_parser('bus') 
parser_serial.add_argument("--fun") 

print parser.parse_args() 

を有します。私は

tester.py --verbose 3 car --boo 1 --foo 2 

としてtestcodeを呼び出すと、私は私が代わりにしたいどのような期待される結果

Namespace(boo='1', foo='2', parser_name='car', verbose=3) 

を取得し、別の名前空間または辞書内の各subparserからの値、

Namespace(subparseargs={boo:'1', foo:'2'}, parser_name='car', verbose=3) 
のようなものです

のように、各サブパーカからの引数は、メインのパーサからの引数と論理的に分離されます(この例ではverbose)。

同じ名前空間(この例ではsubparseargs)の各サブパネルの引数を使用して、これをどのように実現できますか。

import argparse 
from argparse import _HelpAction, _SubParsersAction 

class MyArgumentParser(argparse.ArgumentParser): 
    def parse_args(self, *args, **kw): 
     res = argparse.ArgumentParser.parse_args(self, *args, **kw) 
     from argparse import _HelpAction, _SubParsersAction 
     for x in parser._subparsers._actions: 
      if not isinstance(x, _SubParsersAction): 
       continue 
      v = x.choices[res.parser_name] # select the subparser name 
      subparseargs = {} 
      for x1 in v._optionals._actions: # loop over the actions 
       if isinstance(x1, _HelpAction): # skip help 
        continue 
       n = x1.dest 
       if hasattr(res, n): # pop the argument 
        subparseargs[n] = getattr(res, n) 
        delattr(res, n) 
      res.subparseargs = subparseargs 
     return res 

parser = MyArgumentParser() 
parser.add_argument("--verbose", default = 0, type=int) 

subparsers = parser.add_subparsers(dest = "parser_name") 

parser_lan = subparsers.add_parser('car') 
parser_lan.add_argument("--boo") 
parser_lan.add_argument("--foo") 

parser_serial = subparsers.add_parser('bus') 
parser_serial.add_argument("--fun") 

print parser.parse_args() 
+0

あなたの質問には答えませんが、最新の[argparse wrappers](http://stackoverflow.com/q/13248487/989121)はraw argparseよりもはるかに面白いです。 – georg

答えて

1

私はAnthonのことで、異なるアプローチ(しかし、提案に類似の開発を開始している:あなたが​​の腸の中に少し行きますが、次のスクリプトを変更することはトリックを行う必要があります必要

2

)、はるかに短いコードを思い付く。しかし、私のアプローチが問題の一般的な解決策であるかどうかはわかりません。

class MyArgumentParser(argparse.ArgumentParser): 
    def parse_subargs(self, *args, **kw): 
     # parse as usual 
     args = argparse.ArgumentParser.parse_args(self, *args, **kw) 

     # extract the destination names for top-level arguments 
     topdest = [action.dest for action in parser._actions] 

     # loop over all arguments given in args 
     subargs = {} 
     for key, value in args.__dict__.items(): 

      # if sub-parser argument found ... 
      if key not in topdest: 

       # ... remove from args and add to dictionary 
       delattr(args,key) 
       subargs[key] = value 

     return args, subargs 
:Anthonのは、他のすべての引数は、追加辞書として返されながら、私は、 argsに保管されている「トップレベルの」引数のリストを作成し、新しいメソッドを定義し、提案されたものと類似に

このアプローチへのコメントは、特に私が見落としたすべての抜け穴を歓迎します。

関連する問題