メインコンテンツへスキップ
見出し画像

Python基礎14:コマンドラインオプション(argparse)

    1.概要

     Pythonの標準ライブラリである”argparse”はコマンドラインオプションや引数、サブコマンドのパーサを生成しそれらをパースする機能を提供します。argparseを使用することで、Pythonスクリプトはコマンドラインからの引数を簡単に取り扱うことができます。

    2.基礎用語

     モジュール説明の前に基本的な用語を紹介します。

    1. コマンドライン: テキストベースのインターフェースでユーザーがコンピュータに対して直接命令(コマンド)を入力して操作することができます。例えばWindowsではコマンドプロンプトやPowerShell、LinuxやMacではターミナルが該当します。

    2. サブコマンド (subcommand): メインのコマンドの一部として機能し、特定のタスクを遂行するためのコマンドです。例えば、gitコマンドのclone、pull、pushなどがサブコマンドになります。

    3. コマンドライン引数 (command-line arguments): コマンドラインからプログラムに渡すデータのことを指します。これは、プログラムを実行する際にコマンドラインに直接入力します。例えばpython script.py arg1 arg2というコマンドラインでは、arg1とarg2がコマンドライン引数です。

    4. オプション引数 (optional arguments): プログラムに与えることができるが、必須ではない引数のことを指します。これらは通常、短い名前(-v)と長い名前(--verbose)のどちらか、または両方で指定できます。

    5. Pythonスクリプト: Pythonで書かれたプログラムのことを指します。これは一連の命令が記述されたテキストファイルで".py拡張子"を持ちます。

    6. モジュール (module): Pythonでは、関連する関数・クラス・変数などを一つの.pyファイルにまとめて、他のPythonプログラムから再利用できるようにしたものをモジュールと呼びます(詳細は下記記事参照)。

    7. フラグ (flag): コマンドラインプログラムの動作を変更するために使用されるスイッチのことを指します。通常、オプション引数として提供され、その存在または非存在によってプログラムの動作が変わります。

    8. パーサー (parser): 入力データを解析し、それをプログラムが処理できる内部形式に変換するコンポーネントのことを指します。argparseはコマンドライン引数を解析するためのパーサーを提供しています。

    9. ハードコーディング:ソースコードに直接書き込む形でデータを挿入

    【コラム:モジュールとスクリプト】
     モジュールとスクリプトは両方ともpyファイルで作成しますが、モジュールはimportして使用します。モジュールではimport時に余計な処理が起こらないように"def __name__ == __main__"を指定しますが、スクリプトは直接実行するためこのような処理は不要です。

    3.基本操作

     サンプルとして"Hello World"を出力するPythonスクリプトを作成しました。もし変数を追加して出力を自由に変えたい場合、そのままでは実装できません。argparseを使用することで簡単に引数を渡すことが出来ます。

    [s1.py]
    print('Hello World')
    [Teminal]
    python s1.py
    画像

    3-1.argparseの実装フロー概要

     argparseを使用するための基本的なパターンは以下のようになります。

    1.  argparseをインポート:import argparse

    2.  parserを作成:argparse.ArgumentParser()

    3.  引数を設定:parser.add_argument()

    4.  解析:parser.parse_args()

    3-2.必須の引数

     フローに合わせて渡した引数が出力される簡単なスクリプトを作成します。1つの位置引数(arg1)を設定することで、コマンドラインで引数をスクリプトに提供できます。

    [s1.py]
    import argparse
    
    parser = argparse.ArgumentParser() #parserを作成
    parser.add_argument("arg1", help="arg1 description") #parserに引数を追加
    
    args = parser.parse_args() #parserを解析
    print(args)
    print(type(args))
    print(f'Hello World:{args.arg1}')
    [Teminal]
    python s1.py KIYO
    [OUT]
    Namespace(arg1='KIYO')
    <class 'argparse.Namespace'>       
    Hello World:KIYO

     引数は複数設定も可能です。注意点として上記の方法で設定した場合、コマンドラインで引数を渡さないとエラーが発生します。これは引数設定が必須になっているためです。
     任意の引数を設定するにはオプション引数を利用します。

    [Teminal]
    python s1.py
    [OUT]
    usage: s1.py [-h] arg1
    s1.py: error: the following arguments are required: arg1

    4.オプション引数

     一般的には必須ではなくオプション引数を使用します。本章ではオプション引数の使用方法を紹介します。

    4-1.オプション引数の定義方法

     任意の引数(オプション引数)を渡す場合は"parser.add_argument()"の名前の頭にハイフン(-)を付けます。
     引数名は通常用と省略用の2つ設定でき、通常型は"--"、省略形は"-"で設定します。なお必須引数とは異なりオプション引数は引数名を指定しないとエラーになります。

    [API]
    parser.add_argument(<省略形>, <通常用>, help=<説明文:-h時に確認できる>)
    [Teminal]
    python <モジュール名> -arg <渡したいデータ>

     オプション引数を指定せずに実行することでエラーは発生しませんが、デフォルト値はNoneのためスクリプト実装時には理解が必要です。

    [s2.py]
    import argparse
    
    parser = argparse.ArgumentParser() #parserを作成
    parser.add_argument("-a1", "--arg1", help="arg1 help") #parserに引数を追加
    
    args = parser.parse_args() #parserを解析
    print(args)
    print(type(args))
    print(f'Hello World:{args.arg1}')
    [Teminal]
    python s2.py
    [OUT]
    Namespace(arg1=None)
    <class 'argparse.Namespace'>       
    Hello World:None

     オプション引数を渡すことでスクリプト内で実行できます。コマンドラインは指定していれば省略形でも通常型でもどちらで実行できます。

    [Teminal]
    python s2.py -a KIYO   
    python s2.py --arg1 KIYO 
    [OUT]
    Namespace(arg1='KIYO')
    <class 'argparse.Namespace'>
    Hello World:KIYO

     下記の通り引数名を指定しないとエラーになります。

    [Teminal]
    python s2.py KIYO    
    [OUT]
    usage: s2.py [-h] [-a1 ARG1]
    s2.py: error: unrecognized arguments: KIYO

    4-2.オプション引数設定:add_argument()

     オプション引数に複数の設定ができます。詳細はadd_argument()のAPIに記載しておりますが、ここではよく使用するものを抜粋しました。

    • default:初期値の設定(Noneではなく別の初期値を使用したい)

    • type:型ヒントを設定(※Pythonの関数の型ヒントと異なり、間違った型を入力するとエラーが出るため注意)

    • help:コマンドラインの"-h"または"--help"で引数確認時の説明用

    • action:引数を指定した時のアクション-

      • 引数名を"--flag"や"--verbose"に設定してフラグとして使用

      • アクションは'store', 'store_const', 'store_true', 'append', 'append_const', 'count', 'help', 'version'から設定

    • choices:選択肢を制限(リスト内以外のものだとエラー)

    • nargs:キーワードを複数指定した場合に使用

    • required:オプション引数を必須指定に変更

     簡単なサンプルを作成しました。結果より下記が確認できます。

    • defaultを指定することでオプション引数の初期値がNoneではない

    • actionを指定することでTrue/Falseの切り替えが簡単にできた

    • helpで指定した情報はコマンドラインで確認可能

    [s3.py]
    import argparse
    
    parser = argparse.ArgumentParser() #parserを作成
    #parserに引数を追加
    parser.add_argument("-a1", "--arg1", default='Hello', help="arg1 help") 
    parser.add_argument("--arg2", default='World')
    parser.add_argument("-v", "--verbose", action='store_true') #引数があるときはTrue, ないときはFalse
    
    args = parser.parse_args() #parserを解析
    print(args)
    print(type(args))
    print(f'{args.arg1} {args.arg2}')

    【フラグ無し】

    [Teminal]
    python s3.py 
    [OUT]
    Namespace(arg1='Hello', arg2='World', verbose=False)
    <class 'argparse.Namespace'>
    Hello World

    【フラグあり】

    [Teminal]
    python s3.py -v
    [OUT]
    Namespace(arg1='Hello', arg2='World', verbose=True)
    <class 'argparse.Namespace'>
    Hello World

    【helpで詳細確認】

    [Teminal]
    python s3.py -h
    [OUT]
    usage: s3.py [-h] [-a1 ARG1] [--arg2 ARG2] [-v]
    
    optional arguments:
      -h, --help            show this help message and exit
      -a1 ARG1, --arg1 ARG1
                            arg1 help
      --arg2 ARG2
      -v, --verbose

    5.応用操作

    5-1.引数の確認:-help

     argparseで指定した引数を確認するには"--help"コマンドを指定します。

    [Teminal]
    python s3.py -h
    [OUT]
    usage: s3.py [-h] [-a1 ARG1] [--arg2 ARG2] [-v]
    
    optional arguments:
      -h, --help            show this help message and exit
      -a1 ARG1, --arg1 ARG1
                            arg1 help
      --arg2 ARG2
      -v, --verbose

    6.API

     各クラス・モジュールのAPIを紹介します。

    6-1.parser作成:ArgumentParser

     ArgumentParser オブジェクトのAPIは下記の通りです。

    [API]
    class argparse.ArgumentParser(prog=None, usage=None, description=None, epilog=None, 
                                  parents=[], formatter_class=argparse.HelpFormatter, 
                                  prefix_chars='-', fromfile_prefix_chars=None, 
                                  argument_default=None, conflict_handler='error', 
                                  add_help=True, allow_abbrev=True, exit_on_error=True)

    【引数】

    • prog - プログラム名(デフォルト: os.path.basename(sys.argv[0]))

    • usage - プログラムの利用方法を記述する文字列 (デフォルト: パーサーに追加された引数から生成されます)

    • description - 引数のヘルプの前に表示されるテキスト (デフォルトはテキストなし)

    • epilog - 引数のヘルプの後に表示されるテキスト (デフォルトはテキストなし)

    • parents - ArgumentParser オブジェクトのリストで、このオブジェクトの引数が追加されます

    • formatter_class - ヘルプ出力をカスタマイズするためのクラス

    • prefix_chars - オプションの引数の prefix になる文字集合 (デフォルト: '-')

    • fromfile_prefix_chars - 追加の引数を読み込むファイルの prefix になる文字集合 (デフォルト: None)

    • argument_default - 引数のグローバルなデフォルト値 (デフォルト: None)

    • conflict_handler - 衝突するオプションを解決する方法 (通常は不要)

    • add_help - -h/--help オプションをパーサーに追加する (デフォルト: True)

    • allow_abbrev - 長いオプションが先頭文字列に短縮可能 (先頭の文字が一意) である場合に短縮指定を許可する。(デフォルト: True)

    • exit_on_error - エラーが起きたときに、ArgumentParser がエラー情報を出力して (訳注: プログラムが) 終了する。 (デフォルト: True)

    6-2.引数設定:add_argument() 

     add_argument() メソッドのAPIは下記の通りです。

    [API]
    ArgumentParser.add_argument(name or flags...[, action][, nargs][, const][, default]
                                [, type][, choices][, required][, help][, metavar][, dest])

    【引数】

    • name または flags - 名前かオプション文字列のリスト (例: foo や -f, --foo)。

    • action - コマンドラインにこの引数があったときのアクション。

    • nargs - 受け取るべきコマンドライン引数の数。

    • const - 一部の action と nargs の組み合わせで利用される定数。

    • default - コマンドラインに対応する引数が存在せず、さらに namespace オブジェクトにも存在しない場合に利用される値。

    • type - コマンドライン引数が変換されるべき型。

    • choices - 引数として許される値のシーケンス。

    • required - コマンドラインオプションが省略可能か (オプション引数のみ)。

    • help - 引数が何なのかを示す簡潔な説明。

    • metavar - 使用法メッセージの中で使われる引数の名前。

    • dest - parse_args() が返すオブジェクトに追加される属性名。

    6-3.解析:parse_args()

     parse_args() メソッドのAPIは下記の通りです。

    [API]
    ArgumentParser.parse_args(args=None, namespace=None)

    【引数】

    • args - 解析する文字列のリスト。デフォルトでは sys.argv から取得される。

    • namespace - 属性を代入するオブジェクト。デフォルトでは新しい空の Namespace オブジェクト

    参考記事

    あとがき

     基礎は大事


     
     

    KIYO

     
     
    普段は製造業で企画/開発/設計しております。記事はプログラミング・機械学習、IoT関係の記事をメインで作成し、なるべく1つの記事で知りたいことを網羅していきます。内容は学術的より実装・アウトプット(ほしくなるもの)を重視して作成しています。 面白そうな仕事があればやりたいです!

    あなたへのおすすめ