Python 2.7のargparseは、コマンドライン引数の解析方法を制御できる2つの拡張ポイントを提供します。タイプ関数とアクションクラスです。
組み込みの型とアクションからすると、ベストプラクティスは、型関数に検証/初期化コードを含める必要があり、アクションは名前空間への値の格納に関係する必要があるようです。このアプローチの問題は、副作用のある型チェックコードがある場合です。この簡単な例を考えてみましょう。
from argparse import ArgumentParser, FileType
argp = ArgumentParser()
argp.add_argument('-o', type=FileType('w'), default='myprog.out')
argp.parse_args(['-o', 'debug.out'])
これを実行すると、Pythonがシステム上で2つのファイルを開くことがわかります。ユーザーが引数を指定しない場合にのみ開く方が理にかなっています。myprog.out
debug.out
debug.out
-o
少し調べてみると、argparseは渡された引数またはstr型のデフォルトの引数に対してのみtype関数を呼び出すようです。タイプチェッカーに副作用がある場合、値が渡された場合でもデフォルトで呼び出されるため、これは残念です。したがって、副作用を伴う初期化の場合は、アクションで実行する方がよい場合があります。これに伴う問題は、デフォルト値を指定するとアクションが呼び出されないことです。
次のコードを検討してください。
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>)
誰がその行動を命じましたか?デフォルト値をユーザーから渡された場合とまったく同じように動作させるための適切な方法はありますか?または、値が指定されたときにデフォルトをタイプチェックしないようにしますか?