LoginSignup
6
3

More than 3 years have passed since last update.

argparseで複雑なバリデーションを行う

Last updated at Posted at 2019-10-06

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もセットで指定するようにしておくと良いでしょう。

参考ページ

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3