Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonのargparseでchoicesオプションを使ってコマンドライン引数の値を制限する方法

はじめに

ここでは、ユーザーからテニスのグランドスラム優勝回数を受け付けて処理するプログラムを例に考えてみましょう。2020年時点では、フェデラーとナダルが最多となる20回のグランドスラムタイトルを保持しており、一方、まだ1度も優勝できていない選手も数多く存在します。つまり、有効な値は0〜20回の範囲内ということになります。

まずは、優勝回数を受け付ける基本的なプログラムを作成してみます。

注意: プログラムはターミナルから実行してください。

サンプルコード

import argparse

def get_args():
    """ Function : get_args
    parameters used in .add_argument
    1. metavar - ユーザーにデータ型のヒントを提供する。
       - デフォルトでは、すべての引数は文字列として扱われる。

    2. type - 実際のPythonデータ型
       - (str の前後に引用符がないことに注意)

    3. help - パラメータに関する簡単な説明
    """

    parser = argparse.ArgumentParser(
        description='Example for one positional arguments',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    # 最初の引数として int 型の titles(優勝回数)を追加
    parser.add_argument('titles',
                        metavar='titles',
                        type=int,
                        help='GrandSlam Titles')

    return parser.parse_args()

# main 関数を定義
def main(titles):
    print(f" *** Player had won {titles} GrandSlam titles.")

if __name__ == '__main__':
    args = get_args()
    main(args.titles)

実行結果

プログラムは優勝回数を受け付けられるようになりました。任意の整数(小数は不可)を引数として渡してみましょう。

>>> python test.py 20
*** Player had won 20 GrandSlam titles.
>>> python test.py 50
*** Player had won 50 GrandSlam titles.
>>> python test.py -1
*** Player had won -1 GrandSlam titles.
>>> python test.py 30
*** Player had won 30 GrandSlam titles.

コード自体には技術的な問題はありませんが、機能面では明らかに問題があります。プログラムが負の値を含む任意の数字を優勝回数として受け付けてしまっているのです。

このように受け付ける値の範囲を制限したい場合は、choices オプションを使用します。次の例では、優勝回数を range(0, 20) の範囲、つまり0から19までに制限しています。

choicesオプションで値の範囲を制限する

サンプルコード

import argparse

def get_args():
    """ Function : get_args
    parameters used in .add_argument
    1. metavar - ユーザーにデータ型のヒントを提供する。
       - デフォルトでは、すべての引数は文字列として扱われる。

    2. type - 実際のPythonデータ型
       - (str の前後に引用符がないことに注意)

    3. help - パラメータに関する簡単な説明

    4. choices - ユーザーが入力できる事前に定義された選択肢の範囲
    """

    parser = argparse.ArgumentParser(
        description='Example for one positional arguments',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    # 最初の引数として int 型の titles(優勝回数)を追加
    parser.add_argument('titles',
                        metavar='titles',
                        type=int,
                        choices=range(0, 20),
                        help='GrandSlam Titles')

    return parser.parse_args()

# main 関数を定義
def main(titles):
    print(f" *** Player had won {titles} GrandSlam titles.")

if __name__ == '__main__':
    args = get_args()
    main(args.titles)

実行結果

>>> python test.py 30
usage: test.py [-h] titles
test.py: error: argument titles: invalid choice: 30 (choose from 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
>>> python test.py 10
*** Player had won 10 GrandSlam titles.
>>> python test.py -1
usage: test.py [-h] titles
test.py: error: argument titles: invalid choice: -1 (choose from 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
>>> python test.py 0
*** Player had won 0 GrandSlam titles.
>>> python test.py 20
usage: test.py [-h] titles
test.py: error: argument titles: invalid choice: 20 (choose from 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)

範囲外の値を指定すると、argparseが自動的にエラーメッセージを出力してプログラムを停止してくれることがわかります。

文字列の選択肢を制限する

choices オプションは数値だけでなく、文字列のリストにも対応しています。次の例では、選手名と優勝回数の両方を制限しています。

サンプルコード

import argparse

def get_args():
    """ Function : get_args
    parameters used in .add_argument
    1. metavar - ユーザーにデータ型のヒントを提供する。
       - デフォルトでは、すべての引数は文字列として扱われる。

    2. type - 実際のPythonデータ型
       - (str の前後に引用符がないことに注意)

    3. help - パラメータに関する簡単な説明

    4. choices - ユーザーが入力できる事前に定義された選択肢の範囲
    """

    parser = argparse.ArgumentParser(
        description='Example for one positional arguments',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    # 最初の引数として str 型の player(選手名)を追加
    parser.add_argument('player',
                        metavar='player',
                        type=str,
                        choices=['federer', 'nadal', 'djokovic'],
                        help='Tennis Players')

    # 2番目の引数として int 型の titles(優勝回数)を追加
    parser.add_argument('titles',
                        metavar='titles',
                        type=int,
                        choices=range(0, 20),
                        help='GrandSlam Titles')

    return parser.parse_args()

# main 関数を定義
def main(player, titles):
    print(f" *** {player} had won {titles} GrandSlam titles.")

if __name__ == '__main__':
    args = get_args()
    main(args.player, args.titles)

実行結果

>>> python test.py
usage: test.py [-h] player titles
test.py: error: the following arguments are required: player, titles
>>> python test.py "federer" 30
usage: test.py [-h] player titles
test.py: error: argument titles: invalid choice: 30 (choose from 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
>>> python test.py "murray" 5
usage: test.py [-h] player titles
test.py: error: argument player: invalid choice: 'murray' (choose from 'federer', 'nadal', 'djokovic')
>>> python test.py "djokovic" 17
*** djokovic had won 17 GrandSlam titles.

まとめ

  • choices オプションには許可する値のリストを指定します。ユーザーがリストに含まれない値を入力した場合、argparseはエラーを出してプログラムを停止します。

  • 上記の例では、ユーザーは0〜19の数値から選ぶ必要があり、それ以外の値を指定するとエラーになります。

  • choicesrange(0, 20) のような範囲オブジェクトでも ['federer', 'nadal', 'djokovic'] のような文字列リストでも使用できます。

  • 複数の引数に対してそれぞれ異なる choices を設定することも可能です。

このように argparsechoices オプションを活用すれば、コマンドライン引数の入力値を簡単かつ確実に検証でき、不正な値による予期しない動作を防ぐことができます。

  1. PythonのCerberusでデータ検証(バリデーション)を行う方法を徹底解説

    はじめにPythonのCerberusモジュールは、強力でありながら軽量なデータバリデーション(検証)機能を提供するライブラリです。拡張性に優れた設計になっており、さまざまなアプリケーションやカスタム検証ルールへの対応も容易です。Cerberusでは、まず「スキーマ」と呼ばれる検証ルールの定義を作成し、そのスキーマに対してデータを照合します。条件に一致しなかった場合は、どの箇所が問題だったのかを正確に示すエラーメッセージが出力されるのが特徴です。また、1つのデータフィールドに対して複数の条件を同時に適用することも可能です。Cerberusのインストール方法CerberusはPythonに標準で

  2. Pythonでscikit-learnを使って画像のピクセル値を取得・表示する方法

    データの前処理とは、さまざまなリソース(または単一のリソース)から収集したすべてのデータを、共通のフォーマットや統一されたデータセットへとまとめる作業を指します。現実世界のデータは決して完璧ではないため、欠損セルやエラー、外れ値、列間の不整合などが含まれている可能性があります。画像の場合も同様に、正しく配置されていなかったり、ぼやけていたり、ファイルサイズが非常に大きかったりすることがあります。前処理の目的は、こうした不整合やエラーを取り除くことにあります。画像のピクセル値を取得するには、組み込み関数「flatten」を使用します。画像を読み込んだ後、ピクセル値はデータフレームの形式で保存され