【Python】引数処理にsysよりargparseを使うべき理由

Pythonでコマンドライン引数を処理する方法としてsysモジュールとargparseモジュールが標準で用意されています。(argparseはPython 3.2以降で利用可能)

sysモジュールは以下のように、sys.argvにアクセスすることで引数を取得できます。

Python
import sys

print(sys.argv[0])  # 実行ファイル名(str型)
print(sys.argv[1])  # 1つ目の引数(str型)
print(sys.argv[2])  # 2つ目の引数(str型)

[0]には実行ファイル名が入っており、[1]以降にはコマンドライン引数が順次収納されています。型はいずれもstr型です。

リストとしてシンプルに扱えるため、小規模なプログラムで有効な方法と言えます。

一方argparseモジュールは位置引数だけではなく–optionのような形式のオプションを扱えるほか、それぞれの引数に型やヘルプを設定することができるなど非常に多機能です。(コードは公式ドキュメントより引用)

Python
import argparse

parser = argparse.ArgumentParser(description='Process some integers.')
# 位置引数を追加
parser.add_argument('integers', metavar='N', type=int, nargs='+',
                    help='an integer for the accumulator')
# --sumという形式のオプション引数を追加
parser.add_argument('--sum', dest='accumulate', action='store_const',
                    const=sum, default=max,
                    help='sum the integers (default: find the max)')

args = parser.parse_args()
print(args.accumulate(args.integers))
argparse --- コマンドラインオプション、引数、サブコマンドのパーサー
ソースコード: Lib/argparse.py チュートリアル: このページは API のリファレンス情報が記載しています。 argparse チュートリアル では、コマンドラインの解析についてより優しく説明しています。 argparse ...

複雑な引数を持つスクリプトを作成する場合や、ヘルプを設定できることから他者に公開するスクリプト(一般公開したり、開発チーム内で他の人に使ってもらうスクリプト)はargparseが向いていると思います。

ただ私はテスト用に作るごく小規模なプログラムを除き、なるべくargparseで実装するのが良いと考えています。

理由としてはスクリプト実行のタイミングで型や使い方の不正を検出できるからです。

argparseの場合、間違った型を指定されたり、オプション名の指定ミスなどを実行時のタイミングで検出することが可能で、その場合スクリプト自体がエラーを返しそれ以上先へ処理を進めないようにすることができます。

sysモジュールの場合、間違いを含んだsys.argv[n]にアクセスして処理したタイミングでしか検出することができず、適切な例外処理を行わなければ意図せずスクリプトが停止する可能性もあります。特定の条件でしか引数sys.argv[n]にアクセスされないような場合、テストが不足すればそこに潜むバグの発見が遅れるリスクもあります。

もちろんsysモジュールでもスクリプトの初期段階で十分なチェック処理を入れることで対策は可能ですが、手動でそれらを実装するよりargparseモジュールを使うのが良いと思います。

Pythonのようなインタープリター型、動的型付け言語は基本的にエラーの発見が実行時に該当コードが読み込まれたタイミングになるため、それをスクリプト開始段階でまとめてチェックできることはテストの負担軽減に繋がると考えられます。

外部から入力を受け付ける部分はバグの原因になりやすく、場合によっては脆弱性など致命的なバグに繋がる可能性もあります。argparseを使っても全てが防げるわけではありませんが、可能な限り高度なモジュールを使って処理を行うべきだと思います。

コメント

タイトルとURLをコピーしました