2013-01-18 26 views
5

argparse(または他の何か?)を使用して、各位置引数にデフォルト値のオプション引数を持たせたいと思います。各位置引数のオプションの引数

引数は、ように次のようになります。

script.py arg1 arg2 -o 1 arg3 -o 2 arg4 arg5 

と私はそれは、位置引数とに充填されたデフォルト値を持つオプションの引数のリストのリストのように、使用可能なものにこれを解析します。例えばオプションのデフォルトは、上記の例では0である場合:

つまり
positional = [arg1, arg2, arg3, arg4, arg5] 
optional = [0, 1, 2, 0, 0] 

parser.add_argument('-o', action='append')は、私は位置引数を失うので、各オプションの引数がに関連付けられている私が欲しいものではありません。

+0

あなたにはいくつのポジションの引数があるでしょうか? – mgilson

+0

いいえ、私は引数の数にかかわらず引数をループしたいです。 – bkanuka

答えて

3

は、ここで私が開始するには、合理的な場所であるかもしれない一緒に入れ、簡単なハックです:

import argparse 

class PositionalAction(argparse.Action): 
    def __call__(self,parser,namespace,values,option_string=None): 
     lst = getattr(namespace,self.dest) 
     lst.append(values) 
     parser.last_positional_values = lst 
     all_positional = getattr(namespace,'all_positional',[]) 
     all_positional.append(lst) 
     namespace.all_positional = all_positional 

class AssociateAction(argparse.Action): 
    def __call__(self,parser,namespace,values,option_string=None): 
     try: 
      parser.last_positional_values.append(values) 
     except AttributeError: 
      pass 

parser = argparse.ArgumentParser() 
parser.add_argument('-o',action=AssociateAction,dest=argparse.SUPPRESS) 
junk,unknown = parser.parse_known_args() 

for i,_ in enumerate(unknown): 
    parser.add_argument('arg%d'%i,action=PositionalAction,default=[]) 

print parser.parse_args() 

そして、ここではアクションである:

temp $ python test1.py foo -o 1 bar -o 2 baz qux -o 4 
Namespace(all_positional=[['foo', '1'], ['bar', '2'], ['baz'], ['qux', '4']], arg0=['foo', '1'], arg1=['bar', '2'], arg2=['baz'], arg3=['qux', '4']) 

この問題は、いくつかの課題があります。まず、任意の数の定位置引数を受け取りたい - argparseはそれを好まない。 argparseは何を期待するべきかを知りたい。解決策はパーサーを構築してコマンドラインを解析することですが、argparseには既知の引数だけを解析するように指示します(この場合は、非位置の-o引数はすべて解析されますが、 "位置"引数は解析されません)。 。 parse_known_argsは、(namespace_of_parsed_stuff, uknown_args)という形式のタプルを返すので、これには最適です。だから、未知の議論を知っている - parse_argsを幸せにするために、パーザに位置引数を追加するだけでよい。

さて、カスタムアクションは実際に何をしていますか?位置引数が見つかると(2回目のパスで)、デフォルト(リスト)が取得され、そのリストに値が追加されます(以降、値リストと呼びます)。 パーサーを「値」リストを参照して変更します。また、名前空間から "all_positional"リストを取得します。その属性がない場合は、空のリストを取得するだけです。 "value"リストを "all_positional"リストに追加し、名前空間に戻します。

フラグが-oになると、パーサーが「値」リストを取得し、そのリストに追加値が追加されます。パーサに全く触れることなく同じことをすることができます...(namespace.all_positional[-1] - これはparser.last_positional_valuesと同じリストです)。ほんの少し複雑な場合

+0

あなたが作ったこの魔法は、私が望むもの(またはそれに近いもの)をするようですが、あなたがしたことを完全に理解するまでにはしばらく時間がかかります。それにもかかわらず、ありがとう! – bkanuka

+0

私は、うまくいけばそれが理解できるように助けてくれることについて、いくつかのコメントを追加します。 – mgilson

+0

誤解は、明確さの欠如よりも私の専門知識の欠如と確かに関係しています。 – bkanuka

-1

使用optparse、それは強力です:

op = optparse.OptionParser(usage=usage) 

op.add_option('-c','--cmd',dest='cmd',help="""Command to run. Mutually exclusive with -s. You can use string ${ADDR} to have it replaced with specified host address in the command. """) 

op.add_option('-s','--script',dest='script',help="""Script file to run remotely. Mutually exclusive with -c. A script can have its own arguments; specify the whole command in doublequotes, like "script -arg arg".""") 

op.add_option('-l','--replicate-owner',dest='replicateowner',action="store_true",help="""Replicate (symbolic) owner and (symbolic) group of the file on the remote host, if possible. If remote account with username the same as local account does not exist on remote host, this will silently fail.""") 

# parse cmdline options 
(opts, args) = op.parse_args() 

optsのあなたがあなたの位置引数を取得し、引数と引数の名前を取得します。

値を取る定位引数を持つか、trueまたはfalseとそれ以上のIIRCを設定することができます。

+2

これは特定の質問に答えません。ポスターは{opt、arg}を一般的にどのように使用するかを認識しているようです。 – chepner

0

sys.argvを簡単に実行してみましょう。あなたはargparseが提供する余分な機能を必要としていないようです。例:

argv='script.py arg1 arg2 -o 1 arg3 -o 2 arg4 arg5'.split() 
pos=[] 
opt=[] 
i=1 
while i<len(argv): 
    a=argv[i] 
    if a[:2]!='-o': 
     pos.append(a) 
     opt.append(0) 
    else: 
     i += 1 
     opt[-1]=argv[i] 
    i += 1 
関連する問題