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.out
とdebug.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>)
?デフォルト値がユーザーによって渡されたのとまったく同じように振る舞うようにするには理想的な方法はありますか?値が与えられたときにデフォルトを型チェックしないようにするには?
はい、もちろん、これは動作します。型バリデーターやアクションクラスでそれをやりたいのは、同じような引数を取るコマンドラインツール群を書いていることです。これらの引数を解析し、検証し、インスタンス化するコードを共通化したいのです関数/クラスのセット。引数の処理ルーチンが引数の定義内で指定されている場合、コードはよりクリーンです。 – Nick
あまりにも多くの努力なしにArgumentParserをサブクラス化した場合、これを管理できると思います... – mgilson
振る舞いが単純に型チェッカーとアクションを引数(渡された文字列のどちらか)で呼び出すだけだった場合、ただし、デフォルトのタイプがbasestringでなければ、タイプ検査ステップはスキップされます。 – Nick