2012-09-13 6 views
7

Python 2.7のargparseでは、コマンドライン引数の解析方法を制御できる2つの拡張ポイントがあります。タイプ関数とアクションクラスです。argparseを使用する場合、カスタムタイプまたはアクションで検証および初期化が行われる必要がありますか?

組み込みの型とアクションからは、型関数には検証/初期化コードが含まれている必要があり、アクションは値を名前空間に格納することに関係しているようです。このアプローチの問題は、副作用を伴うタイプチェックコードがある場合です。この単純な例を考えてみましょう:

from argparse import ArgumentParser, FileType 
argp = ArgumentParser() 
argp.add_argument('-o', type=FileType('w'), default='myprog.out') 
argp.parse_args(['-o', 'debug.out']) 

これを実行すると、Pythonはシステム上のファイル、myprog.outdebug.outを開きますあなたを見つけます。ユーザーが-o引数を指定しないと、debug.outを開くのが理にかなっています。

ちょっと覗いてみると、argparseは渡された引数またはstr型のデフォルトの引数に対してのみ型関数を呼び出すようです。これは、値が渡されてもデフォルトで呼び出されるため、型チェッカーに副作用がある場合は残念です。したがって、副作用を伴う初期化のためには、おそらくそれをアクションで行うほうがよいでしょう。この問題は、デフォルト値を指定するとアクションが呼び出されないことになります。

次のコードを考えてみましょう:

from argparse import ArgumentParser, Action 

def mytype(arg): 
    print 'checking type for ' + repr(arg) 
    return arg 

class OutputFileAction(Action): 
    def __call__(self, parser, namespace, values, option_string=None): 
     print 'running action for ' + repr(values) 
     try: 
      outstream = open(values, 'w') 
     except IOError as e: 
      raise ArgumentError('error opening file ' + values) 
     setattr(namespace, self.dest, outstream) 

argp = ArgumentParser() 
argp.add_argument('-o', type=mytype, action=OutputFileAction, default='myprog.out') 

を今すぐそれを使おう:

その行動を命じ
>>> argp.parse_args([]) 
checking type for 'myprog.out' 
Namespace(o='myprog.out') 
>>> argp.parse_args(['-o', 'debug.out']) 
checking type for 'myprog.out' 
checking type for 'debug.out' 
running action for 'debug.out' 
Namespace(o=<open file 'debug.out', mode 'w' at 0x2b7fced07300>) 

?デフォルト値がユーザーによって渡されたのとまったく同じように振る舞うようにするには理想的な方法はありますか?値が与えられたときにデフォルトを型チェックしないようにするには?

答えて

2

私が知っている限り、これを行うには "賢明な"方法はありません。もちろん、Namespaceparse_argsから返さ後処理オフしてからtype変換を残すために簡単です:

args = argp.parse_args() 
args.o = open(args.o,'w') 

が、私はそれはあなたが探しているものではありませんと仮定します。

+1

はい、もちろん、これは動作します。型バリデーターやアクションクラスでそれをやりたいのは、同じような引数を取るコマンドラインツール群を書いていることです。これらの引数を解析し、検証し、インスタンス化するコードを共通化したいのです関数/クラスのセット。引数の処理ルーチンが引数の定義内で指定されている場合、コードはよりクリーンです。 – Nick

+0

あまりにも多くの努力なしにArgumentParserをサブクラス化した場合、これを管理できると思います... – mgilson

+0

振る舞いが単純に型チェッカーとアクションを引数(渡された文字列のどちらか)で呼び出すだけだった場合、ただし、デフォルトのタイプがbasestringでなければ、タイプ検査ステップはスキップされます。 – Nick

関連する問題