Pythonの引数解析モジュール、argparseを使う際、引数にちょっと複雑な書式を要求したい場合もあります。
そのような場合に、独自の検証コードを書くことで、正規表現など様々な方法でバリデーションを行うことができます。
まずはプログラム
まずはプログラムから。
import argparse
class rex_check(object):
# バリデーションのためのクラス
def __init__(self, pattern):
# 初期化
self.pattern = pattern
def __contains__(self, val):
# マッチ処理を行う
return re.match(self.pattern, val)
def __iter__(self):
# エラー時にコンソールに表示される(invalid choice: 値 (choose from なんとか)
# print_help()のmetavarでも表示されるので、metaverオプションを使って隠す
return iter(("str", self.pattern))
parser = ArgumentParser()
parser.add_argument("-r", "--rect",
type=str
metavar="RECT",
choices=rex_check(r"(?:\d+:){3}\d+"),
default=[])
# ・・・そのほかのオプション指定・・・
と、しておくと・・・
parser.parse_args(["-r", "abc"]) # NG
parser.parse_args(["-r", "1:1:1"]) # NG
parser.parse_args(["-r", "1:1:1:"]) # NG
parser.parse_args(["-r", "1:1:1:1"]) # OK
ちゃんと正規表現のパターンマッチが行われていることがわかると思います。
仕組み
ArgumentParser#add_argumnet()
メソッドの引数choices
は、本来配列を渡すことで、パラメータのとりうる値をその値に限定することができるというオプションですが、__contains__()
と__iter__()
を実装しているオブジェクトを渡すことで、そのオブジェクトによる検証を行うことができます。
内容はコメントに書いたとおりですが。
-
__contains__(self, val)
:valがパラメータの値。バリデーションOKの場合はTrue -
__iter__(self)
:戻り値はパラメータの解析に失敗したときに出るエラーメッセージおよび、metavar
に使用される。
__iter__(self)
はArgumentParser#print_help()
メソッドで表示されるmetavar
にも利用されるため、基本的にはここにクラスを指定した場合は、metavar
もセットで指定するようにしておくと良いでしょう。