Pythonコマンドライン引数 超基本から徹底解説
はじめに
Pythonスクリプトを作成する際、プログラムの挙動を外部から変更したいという要求は頻繁に発生します。例えば、処理するファイル名を指定したい、計算のパラメータを変えたい、デバッグモードで実行したい、といったケースです。このような場合、プログラムのコードを毎回書き換えるのは非効率的ですし、自動化にも向きません。そこで活躍するのが「コマンドライン引数」です。
コマンドライン引数とは、Pythonスクリプトを実行する際に、コマンドライン(ターミナルやコマンドプロンプト)からプログラムに渡す追加の情報のことです。これにより、スクリプトの柔軟性が格段に向上し、様々な状況に対応できるようになります。
この情報は、コマンドラインからプログラムを実行する際のコマンドの後ろにスペース区切りで記述されます。例えば、python your_script.py arg1 arg2 のように指定します。your_script.py がスクリプト名、arg1 と arg2 がコマンドライン引数です。
コマンドライン引数を理解し、使いこなすことは、Pythonプログラミングにおいて非常に重要です。特に、データ処理、自動化スクリプト、ユーティリティツールなどを開発する際には必須のスキルと言えるでしょう。
この記事では、Pythonにおけるコマンドライン引数の扱いの「超基本」から始め、標準ライブラリを使ったより高度な方法まで、徹底的に解説します。約5000語をかけて、コマンドライン引数の仕組み、受け取り方、様々な処理方法、そして実用的な使い方までを網羅します。この記事を読めば、あなたのPythonスクリプトをよりパワフルで柔軟なものにするための知識が身につくはずです。
さあ、Pythonコマンドライン引数の世界に飛び込みましょう。
コマンドライン引数の「超基本」:sys.argv
Pythonスクリプトをコマンドラインから実行する際に、渡された引数を最も簡単に取得する方法は、標準ライブラリである sys モジュールの argv という属性を使うことです。
sys モジュールは、Pythonインタープリタとその環境に関する情報を提供するモジュールです。sys.argv は、このモジュールが提供する属性の一つで、コマンドライン引数のリストを保持しています。
Pythonスクリプトをコマンドラインから実行する方法
まず、Pythonスクリプトをコマンドラインから実行する基本的な方法を確認しておきましょう。通常は、ターミナル(macOS/Linux)やコマンドプロンプト(Windows)を開き、以下のように実行します。
bash
python your_script.py
または、環境によってはPythonのバージョンを指定して実行することもよくあります。
bash
python3 your_script.py
このコマンドは、指定したパスにある your_script.py という名前のPythonスクリプトを、Pythonインタープリタを使って実行するという指示です。
引数を渡す方法
スクリプトに引数を渡す場合は、スクリプト名の後ろにスペース区切りで値を記述します。
bash
python your_script.py argument1 argument2 value3
この例では、argument1、argument2、value3 という3つの引数を your_script.py に渡しています。
sys.argv とは何か?
では、渡された引数はスクリプトの中でどのように受け取るのでしょうか?ここで sys.argv の登場です。
sys.argv は、スクリプト名自身を含む、コマンドラインで指定されたすべての項目を要素として持つ「リスト」です。
具体的な中身は以下のようになります。
sys.argv[0]: これは常に、実行されたスクリプトの名前(またはスクリプトへのパス)になります。sys.argv[1]: コマンドラインでスクリプト名の次に指定された最初の引数です。sys.argv[2]: コマンドラインで指定された2番目の引数です。- …以下、指定された引数の数だけ要素が続きます。
要素はすべて「文字列」として扱われます。たとえコマンドラインで数値を入力したとしても、sys.argv の要素としては文字列として格納されます。
簡単なコード例 (sys.argv をprintするだけ)
sys.argv の仕組みを理解するために、最も簡単な例を見てみましょう。以下のコードを simple_args.py という名前で保存してください。
“`python
simple_args.py
import sys
print(“スクリプト名を含む引数リスト:”, sys.argv)
print(“引数の個数:”, len(sys.argv))
引数があれば、最初の引数と2番目の引数を表示してみる (エラー回避のため条件分岐)
if len(sys.argv) > 1:
print(“最初の引数 (sys.argv[1]):”, sys.argv[1])
if len(sys.argv) > 2:
print(“2番目の引数 (sys.argv[2]):”, sys.argv[2])
print(“— 各引数を順番に表示 —“)
for i, arg in enumerate(sys.argv):
print(f”sys.argv[{i}]: {arg}”)
“`
実行例とその出力
保存した simple_args.py を様々なパターンで実行してみましょう。
1. 引数なしで実行した場合:
bash
python simple_args.py
出力:
スクリプト名を含む引数リスト: ['simple_args.py']
引数の個数: 1
--- 各引数を順番に表示 ---
sys.argv[0]: simple_args.py
解説:
引数を何も指定しなかった場合、sys.argv にはスクリプト名である 'simple_args.py' だけがリストとして格納されます。リストの長さは1です。sys.argv[1] 以降は存在しないため、条件分岐の中の print 文は実行されません。
2. 引数をいくつか指定して実行した場合:
bash
python simple_args.py hello world 123
出力:
スクリプト名を含む引数リスト: ['simple_args.py', 'hello', 'world', '123']
引数の個数: 4
最初の引数 (sys.argv[1]): hello
2番目の引数 (sys.argv[2]): world
--- 各引数を順番に表示 ---
sys.argv[0]: simple_args.py
sys.argv[1]: hello
sys.argv[2]: world
sys.argv[3]: 123
解説:
この場合、sys.argv にはスクリプト名に加えて、指定した 'hello'、'world'、'123' という3つの文字列が順番に要素として追加されます。リストの長さは4になります。sys.argv[1] は 'hello'、sys.argv[2] は 'world'、sys.argv[3] は '123' となります。
3. 引数にスペースを含む場合:
引数にスペースを含めたい場合は、その引数を引用符 (' または ") で囲みます。
bash
python simple_args.py "hello world" "another argument"
出力:
スクリプト名を含む引数リスト: ['simple_args.py', 'hello world', 'another argument']
引数の個数: 3
最初の引数 (sys.argv[1]): hello world
2番目の引数 (sys.argv[2]): another argument
--- 各引数を順番に表示 ---
sys.argv[0]: simple_args.py
sys.argv[1]: hello world
sys.argv[2]: another argument
解説:
引用符で囲まれた部分は、一つの引数として扱われます。'hello world' と 'another argument' がそれぞれ一つの要素として sys.argv に格納されていることがわかります。
このように、sys.argv を使うことで、コマンドラインから渡された引数をPythonスクリプト内で簡単にリストとして取得できます。これがPythonでコマンドライン引数を扱う上での最も基本的な方法です。
sys.argv の詳細な理解
前のセクションでは sys.argv の基本的な使い方を見ました。ここでは、さらに sys.argv を詳細に理解し、実際に引数を使った処理を行うための注意点などを掘り下げていきます。
sys モジュールのインポート
sys.argv を使うためには、必ずスクリプトの冒頭で import sys を記述する必要があります。これは、argv が sys モジュールの一部であるためです。
“`python
import sys
これ以降で sys.argv が使えます
“`
sys.argv は常にリスト
繰り返しになりますが、sys.argv はどのような場合でも常にリストです。引数がない場合でも、空のリストではなく、スクリプト名のみを含むリスト [スクリプト名] になります。この性質を利用して、len(sys.argv) で引数の個数(スクリプト名を含む)を調べることができます。
要素はすべて文字列
これも重要な点です。コマンドラインで数字 (123) や小数点を含む数 (3.14) を引数として渡しても、sys.argv の中では '123' や '3.14' のような「文字列」として格納されます。もしこれらの値を数値として扱いたい場合は、明示的な型変換が必要です。
インデックスアクセス
sys.argv はリストなので、インデックス(添え字)を使って個々の引数にアクセスできます。
sys.argv[0]: スクリプト名sys.argv[1]: 1番目の引数sys.argv[2]: 2番目の引数- …
引数の個数を取得 (len(sys.argv))
引数の個数を知るには、リストの長さを取得する組み込み関数 len() を使います。
“`python
import sys
num_args = len(sys.argv)
print(f”合計 {num_args} 個の項目が渡されました (スクリプト名を含む)。”)
print(f”引数の個数は {num_args – 1} 個です。”)
“`
引数の個数(スクリプト名を含まない)は len(sys.argv) - 1 で求められます。
数値として使いたい場合の型変換
コマンドライン引数として渡された文字列を数値(整数や浮動小数点数)としてプログラム内で利用したい場合は、int() や float() といった組み込み関数を使って型変換を行います。
“`python
import sys
if len(sys.argv) > 2:
arg1 = sys.argv[1] # 1番目の引数は文字列
arg2 = sys.argv[2] # 2番目の引数も文字列
try:
# 1番目の引数を整数に変換
num1 = int(arg1)
# 2番目の引数を浮動小数点数に変換
num2 = float(arg2)
print(f"文字列として受け取った引数: '{arg1}', '{arg2}'")
print(f"数値に変換した引数: {num1} (int), {num2} (float)")
print(f"計算結果 (num1 + num2): {num1 + num2}")
except ValueError:
# 数値に変換できない文字列が渡された場合
print(f"エラー: 引数 '{arg1}' または '{arg2}' を数値に変換できませんでした。")
print("数値を引数として指定してください。")
else:
print(“使用方法: python your_script.py <整数> <小数点数>”)
“`
このコードを type_conversion.py として保存し、実行してみましょう。
bash
python type_conversion.py 10 3.14
出力:
文字列として受け取った引数: '10', '3.14'
数値に変換した引数: 10 (int), 3.14 (float)
計算結果 (num1 + num2): 13.14
引数が数値にうまく変換されていることがわかります。
次に、数値として変換できない文字列を渡してみましょう。
bash
python type_conversion.py hello world
出力:
エラー: 引数 'hello' または 'world' を数値に変換できませんでした。
数値を引数として指定してください。
try...except ValueError ブロックにより、数値変換できない場合にエラーメッセージを表示するようになっています。コマンドライン引数を扱う際は、このようにユーザーが意図しない値を入力する可能性を考慮し、エラーハンドリングを適切に行うことが重要です。
引数がない場合の注意点(IndexError)
sys.argv から特定のインデックスの要素にアクセスする際、そのインデックスが存在しない場合は IndexError が発生します。
例えば、以下のコードは引数が1つ以上あることを前提としています。
“`python
import sys
BAD EXAMPLE: これだけだと引数がない場合にエラー
first_arg = sys.argv[1]
print(f”最初の引数: {first_arg}”)
“`
引数なしで実行すると、sys.argv は ['script_name.py'] となり、sys.argv[1] は存在しないため IndexError: list index out of range が発生します。
これを避けるためには、要素にアクセスする前に len(sys.argv) を使って引数の個数を確認する必要があります。
“`python
import sys
if len(sys.argv) > 1: # スクリプト名以外に引数があるかチェック
first_arg = sys.argv[1]
print(f”最初の引数: {first_arg}”)
else:
print(“引数が指定されていません。”)
“`
このように、sys.argv を使う場合は、必ず引数の個数チェックと型変換時のエラーハンドリングを組み合わせる必要があります。
コード例:複数の引数を処理
sys.argv を使って複数の引数を処理する例をもう少し見てみましょう。ここでは、指定されたファイル名を開いて内容を表示するスクリプトを作成します。
“`python
display_file.py
import sys
期待される引数の個数: スクリプト名 + ファイル名 = 2
expected_arg_count = 2
if len(sys.argv) != expected_arg_count:
print(f”使用方法: python {sys.argv[0]} <ファイル名>”)
sys.exit(1) # エラー終了を示す
file_name = sys.argv[1] # 最初の引数がファイル名
try:
with open(file_name, ‘r’, encoding=’utf-8′) as f:
content = f.read()
print(f”— ファイル ‘{file_name}’ の内容 —“)
print(content)
print(“————————————“)
except FileNotFoundError:
print(f”エラー: ファイル ‘{file_name}’ が見つかりませんでした。”)
sys.exit(1) # エラー終了
except Exception as e:
print(f”ファイル読み込み中にエラーが発生しました: {e}”)
sys.exit(1) # エラー終了
sys.exit(0) # 正常終了を示す
“`
このスクリプトは、コマンドラインでちょうど1つの引数(ファイル名)が指定された場合にのみ動作します。それ以外の数の引数が指定された場合は、使用方法を表示して終了します。ファイルが存在しない場合もエラーメッセージを表示します。
テスト用のファイル test.txt を作成します。
これは
テストファイルです。
実行例:
bash
python display_file.py test.txt
出力:
“`
— ファイル ‘test.txt’ の内容 —
これは
テストファイルです。
“`
引数を指定しない場合:
bash
python display_file.py
出力:
使用方法: python display_file.py <ファイル名>
存在しないファイルを指定した場合:
bash
python display_file.py non_existent_file.txt
出力:
エラー: ファイル 'non_existent_file.txt' が見つかりませんでした。
この例のように、sys.argv を使う場合でも、引数の個数チェック、型変換、そしてファイルアクセスなどの失敗に対するエラーハンドリングを組み合わせることで、ある程度実用的なスクリプトを作成できます。
しかし、sys.argv だけでは不便な点も多いことに気づくでしょう。次のセクションでは、その課題と、より高機能な引数処理ライブラリの必要性について説明します。
より実用的な引数処理:なぜ sys.argv だけでは不十分か
sys.argv はシンプルで直接的ですが、引数を扱う上でいくつかの大きな課題があります。これらの課題は、スクリプトが複雑になったり、ユーザーフレンドリーなインターフェースを提供しようとしたりする場合に顕著になります。
sys.argv の主な課題は以下の通りです。
-
引数の意味が分かりにくい(位置引数のみ):
sys.argvで取得できる引数は、コマンドラインで指定された順番通りの文字列のリストです。どの引数が何を示しているのかは、コードを読むか、別途ドキュメントを読むかしなければ分かりません。例えばpython script.py input.txt output.txt 100とした場合、input.txtは入力ファイル、output.txtは出力ファイル、100は何かの上限値、といった解釈はプログラマーしか知ることができません。引数の「名前」がないため、意味が分かりにくいのです。 -
引数の順序に依存する:
sys.argvを使う場合、引数は必ず特定の順番で指定される必要があります。上記の例でpython script.py 100 input.txt output.txtと順番を間違えると、プログラムは100を入力ファイル名として扱おうとするなど、誤動作の原因となります。ユーザーは引数の順番を正確に覚えておく必要があります。 -
必須引数とオプション引数の区別がない:
sys.argvは渡されたすべての文字列を等しく扱います。プログラムの実行に必須な引数と、指定しなくてもデフォルト値で動作するオプションの引数を区別する仕組みがありません。どの引数が必須でどれがオプションなのかをユーザーに伝えるのは難しく、またプログラム側でそれをチェックするコードを自分で書く必要があります。 -
ヘルプメッセージの表示機能がない: 多くのコマンドラインツールは、
-hや--helpという引数を指定すると、そのツールの使い方や利用可能なオプションの一覧を表示してくれます。これはユーザーにとって非常に役立つ機能ですが、sys.argvを使って自分で実装するのは面倒です。引数の定義、説明、デフォルト値などを整理して整形し、表示するコードをゼロから書く必要があります。 -
エラーチェックが手動で面倒: 引数の個数が正しいか、型変換が可能か、値が有効な範囲内か、といったチェックをすべて手動で記述する必要があります。引数の種類や数が増えるにつれて、エラーチェックのコードは複雑になり、バグの温床となりがちです。また、エラーメッセージの表示も自分で整形する必要があります。
-
フラグ (
-v,--help) やキー・バリュー形式 (--output=result.txt) の引数を扱えない:sys.argvは単純なスペース区切りの文字列リストであるため、-v(詳細表示フラグ) や--output result.txtのように、オプション名の前にハイフンが付くような、一般的なコマンドライン引数の形式をそのままでは扱えません。これらの形式の引数を解析するためには、自分で文字列をパース(解析)するコードを書く必要があります。これは非常に手間がかかり、エラーも発生しやすい作業です。
これらの課題から、sys.argv は非常にシンプルなスクリプトや、引数の数が少なく順序も固定されている場合にのみ適していると言えます。より柔軟で、ユーザーフレンドリーなコマンドラインインターフェースを持つスクリプトを作成したい場合は、これらの課題を解決してくれる別の方法を使うのが一般的です。
Pythonの標準ライブラリには、これらの課題を解決するために設計された強力なモジュールが用意されています。それが argparse です。次のセクションでは、この argparse の使い方を超基本から詳しく見ていきます。
標準ライブラリ argparse の基本
argparse モジュールは、コマンドライン引数を解析するための標準ライブラリです。複雑な引数の定義、自動的なヘルプメッセージ生成、値の型変換、必須・オプション引数の区別、エラーハンドリングなど、sys.argv だけでは困難だった多くの機能を簡単に実現できます。
argparse を使うことで、堅牢でユーザーフレンドリーなコマンドラインインターフェースを効率的に構築できます。
argparse とは?
argparse は、開発者がプログラムが受け取るコマンドライン引数を定義し、その引数を自動的に解析してPythonオブジェクトとして利用できるようにするライブラリです。ユーザーが不正な引数を指定した場合には、自動的にエラーメッセージを表示してプログラムを終了させる機能も持っています。また、標準で -h または --help オプションによるヘルプメッセージ表示機能を提供します。
基本的な使い方
argparse を使う基本的な手順は以下の通りです。
import argparse: まず、argparseモジュールをインポートします。ArgumentParserオブジェクトの作成: 引数の解析を管理するArgumentParserオブジェクトを作成します。add_argument()メソッドで引数を定義: プログラムが受け取る引数を一つずつ定義します。位置引数、オプション引数、それぞれの名前、期待する値の型、説明などを指定します。parse_args()メソッドで引数を解析: コマンドラインで実際に指定された引数を解析させます。このメソッドは、定義に従って引数の文字列を適切な型に変換し、それらを属性として持つ「名前空間オブジェクト」を返します。- 解析結果へのアクセス:
parse_args()が返した名前空間オブジェクトの属性として、解析された引数の値にアクセスします。
これらの手順を具体的なコード例で見ていきましょう。以下のコードを argparse_basic.py という名前で保存してください。
“`python
argparse_basic.py
import argparse
1. ArgumentParser オブジェクトの作成
プログラム全体の簡単な説明 (description) を加えることができます
parser = argparse.ArgumentParser(description=’これはargparseの基本的な使い方を示すサンプルスクリプトです。’)
3. add_argument() メソッドで引数を定義
位置引数の定義 (dest で名前を指定、または単に名前なしで定義)
位置引数は通常、必須となります
parser.add_argument(
‘input_file’, # 引数の名前。parse_args()の結果にこの名前でアクセスします。
help=’処理する入力ファイルの名前を指定します。’ # –help オプションで表示される説明文
)
オプション引数の定義 (先頭に – または — がつく)
type で期待する値の型を指定できます。指定しない場合は文字列 (str) です。
parser.add_argument(
‘–output’, # 短いオプション名 -o も追加可能: ‘-o’, ‘–output’
help=’結果を書き込む出力ファイルの名前を指定します。(オプション)’
)
型を指定するオプション引数
parser.add_argument(
‘–count’,
type=int, # int 型に変換する
default=1, # デフォルト値
help=’処理を繰り返す回数を指定します。(デフォルトは1)’
)
値を取らないフラグオプション (指定されたら True、されなければ False)
parser.add_argument(
‘–verbose’,
action=’store_true’, # 引数に値は不要。指定があれば True を格納
help=’詳細な処理状況を表示します。(オプション)’
)
4. parse_args() メソッドで引数を解析
コマンドラインで指定された引数を解析し、結果を args という名前空間オブジェクトに格納
args = parser.parse_args()
5. 解析結果へのアクセス
args オブジェクトの属性として、add_argument() で指定した名前を使って引数の値にアクセス
print(f”入力ファイル名: {args.input_file}”)
オプション引数は指定されなかった場合、デフォルト値または None になります
if args.output: # args.output が None や空文字列でなければ (指定されていれば)
print(f”出力ファイル名: {args.output}”)
else:
print(“出力ファイルは指定されませんでした。”)
print(f”処理回数: {args.count}”) # デフォルト値が設定されている場合は必ず値があります
if args.verbose: # args.verbose は store_true なので True/False
print(“詳細モードが有効です。”)
else:
print(“詳細モードは無効です。”)
引数の値を使って簡単な処理をする例
args.count は int 型に変換されているので、そのまま計算に使える
print(“-” * 20)
print(f”{args.input_file} を {args.count} 回処理します。”)
if args.output:
print(f”結果は {args.output} に出力されます。”)
“`
実行例(argparse_basic.py)
様々な引数のパターンで実行してみましょう。
1. ヘルプメッセージの表示:
argparse はデフォルトで -h または --help オプションを認識し、定義した引数に基づいたヘルプメッセージを自動生成します。
bash
python argparse_basic.py -h
出力:
“`
usage: argparse_basic.py [-h] [–output OUTPUT] [–count COUNT] [–verbose] input_file
これはargparseの基本的な使い方を示すサンプルスクリプトです。
positional arguments:
input_file 処理する入力ファイルの名前を指定します。
options:
-h, –help show this help message and exit
–output OUTPUT 結果を書き込む出力ファイルの名前を指定します。(オプション)
–count COUNT 処理を繰り返す回数を指定します。(デフォルトは1)
–verbose 詳細な処理状況を表示します。(オプション)
“`
この自動生成されるヘルプメッセージは非常に便利です。どの引数が利用可能か、どのような意味を持つか、デフォルト値は何かなどが一目で分かります。add_argument() で指定した help メッセージがここに表示されます。
2. 必須の位置引数のみを指定して実行:
input_file は位置引数として定義されており、デフォルトでは必須です。
bash
python argparse_basic.py my_data.csv
出力:
“`
入力ファイル名: my_data.csv
出力ファイルは指定されませんでした。
処理回数: 1
詳細モードは無効です。
my_data.csv を 1 回処理します。
“`
input_file の値が args.input_file に格納されています。オプション引数は指定されていないため、args.output は None、args.count はデフォルト値の 1、args.verbose は False となっています。
3. 必須引数とオプション引数を組み合わせて実行:
bash
python argparse_basic.py input.txt --output result.txt --count 5 --verbose
出力:
“`
入力ファイル名: input.txt
出力ファイル名: result.txt
処理回数: 5
詳細モードが有効です。
input.txt を 5 回処理します。
結果は result.txt に出力されます。
“`
指定したすべてのオプション引数が適切に解析され、それぞれの値が args オブジェクトの対応する属性に格納されていることがわかります。--count 5 の 5 は type=int により整数 5 として格納されています。--verbose は action='store_true' により True として格納されています。
4. オプション引数の順序を変えて実行:
argparse を使うと、オプション引数の順序は任意になります。
bash
python argparse_basic.py --count 10 --verbose --output final.log source.dat
出力:
“`
入力ファイル名: source.dat
出力ファイル名: final.log
処理回数: 10
詳細モードが有効です。
source.dat を 10 回処理します。
結果は final.log に出力されます。
“`
位置引数である source.dat は引数リストの最後の位置にありますが、定義に従って正しく args.input_file に格納されています。オプション引数も順不同で指定できます。
5. 必須引数を指定しなかった場合:
argparse は必須引数が指定されなかった場合に自動的にエラーメッセージを表示し、プログラムを終了します。
bash
python argparse_basic.py
出力:
usage: argparse_basic.py [-h] [--output OUTPUT] [--count COUNT] [--verbose] input_file
argparse_basic.py: error: the following arguments are required: input_file
このように、argparse は引数の定義に基づいて自動的に入力チェックとエラー報告を行ってくれます。
6. 型変換に失敗する値を指定した場合:
--count オプションは type=int と定義されていますが、整数に変換できない文字列を指定してみましょう。
bash
python argparse_basic.py myfile.txt --count abc
出力:
usage: argparse_basic.py [-h] [--output OUTPUT] [--count COUNT] [--verbose] input_file
argparse_basic.py: error: argument --count: invalid int value: 'abc'
argparse が自動的に型変換のエラーを検知し、分かりやすいエラーメッセージを表示して終了します。sys.argv の場合、自分で try...except ValueError ブロックを書く必要がありましたが、argparse はこれを肩代わりしてくれます。
argparse を使うメリットの再確認
sys.argv と比較して、argparse を使うことのメリットは明らかです。
- 明確な引数定義: プログラムがどのような引数を期待しているかがコード上で明確になります。
- 自動ヘルプメッセージ: ユーザーにとって非常に便利な使い方の説明が自動で生成されます。
- 自動エラーチェック: 必須引数の漏れや型エラーなどを自動的に検知し、適切なメッセージでユーザーに通知します。
- 柔軟な引数指定: 位置引数、オプション引数(フラグや値付き)、短い形式、長い形式など、多様な指定方法に対応できます。順序も自由に指定できます(位置引数は定義順)。
- 自動型変換: 数値やその他の型への変換を自動で行い、コードがシンプルになります。
- ユーザーフレンドリー: エラーメッセージやヘルプメッセージが分かりやすいため、ユーザーがプログラムを正しく使いやすくなります。
これらのメリットから、コマンドライン引数を扱うスクリプトを開発する際には、ほとんどの場合 argparse を使うことが推奨されます。
argparse のより進んだ使い方
argparse は基本的な使い方だけでも非常に便利ですが、さらに多くの機能を提供しており、より複雑な要件にも対応できます。ここでは、argparse のより進んだ使い方について詳しく見ていきましょう。
引数の種類と定義の詳細
add_argument() メソッドには、引数の挙動を細かく制御するための様々な引数(キーワード引数)があります。
-
位置引数 vs オプション引数
- 位置引数:
add_argument()の最初の引数にハイフン (-) やダブルハイフン (--) を付けずに名前を指定します(例:'input_file')。コマンドラインでは引数の順番が重要になります。 - オプション引数: 最初の引数にハイフンまたはダブルハイフンを付けて名前を指定します(例:
'-o','--output')。コマンドラインでは引数の前にオプション名を付けます。順序は任意です。
- 位置引数:
-
短いオプション (
-o) と長いオプション (--output)- オプション引数を定義する際に、
parser.add_argument('-o', '--output', ...)のように複数の文字列を指定できます。最初の文字列が短いオプション名、それ以降が長いオプション名として扱われます。通常、短いオプションは1文字、長いオプションは複数の単語をハイフンでつなぎます。ユーザーはどちらか好きな方を使って引数を指定できます。
- オプション引数を定義する際に、
-
値を取るオプションと取らないオプション (フラグ)
- デフォルトでは、オプション引数はその後に値を伴うと解釈されます(例:
--output result.txt)。 - 値を取らず、単に存在するかどうかで真偽を示すフラグオプションは、
action引数を使って定義します。action='store_true': オプションが指定された場合にTrueを格納し、指定されなかった場合にFalseを格納します。action='store_false': オプションが指定された場合にFalseを格納し、指定されなかった場合にTrueを格納します。
- 例:
parser.add_argument('--verbose', action='store_true', help='詳細モードを有効にします')
- デフォルトでは、オプション引数はその後に値を伴うと解釈されます(例:
-
typeの活用type引数には、引数の値を変換したい型を指定します。組み込み型 (int,float,str,bool– ただし bool は少し特殊、後述) の他に、関数やクラスを指定することもできます。例えばtype=openとすれば、指定されたファイル名を読み取りモードで開いたファイルオブジェクトを取得できます(ファイルが開けなかった場合はエラーになります)。- 例:
parser.add_argument('--count', type=int)、parser.add_argument('--input', type=open, help='入力ファイルを指定') - 注意点:
type=boolは期待通りに動作しないことが多いです。コマンドライン引数はすべて文字列として渡されるため、例えば"True"という文字列をbool()に渡してもTrueにはなりません(空文字列以外の文字列はbool()ではすべてTrueと評価されるため)。真偽を示すオプションは、通常action='store_true'またはaction='store_false'を使うのが一般的です。
-
defaultの重要性default引数を指定すると、そのオプション引数がコマンドラインで指定されなかった場合に、代わりに使われるデフォルト値を設定できます。これにより、オプション引数を必須ではなくすることができます。- 例:
parser.add_argument('--count', type=int, default=10) - 位置引数に対しても
defaultを設定できますが、これはその位置に引数が全く指定されなかった場合にのみ適用されるため、通常はあまり使いません。位置引数はデフォルトで必須として扱うことが多いです。
-
requiredrequired=Trueを指定すると、そのオプション引数を必須にすることができます。必須オプションが指定されなかった場合、argparseはエラーメッセージを表示して終了します。位置引数はデフォルトでrequired=Trueと同じ挙動をしますが、明示的に指定することもできます。- 例:
parser.add_argument('--config', required=True, help='設定ファイルを指定します。')
-
choicesで引数の値を制限choices引数にリストやタプルを指定すると、引数の値がそのリストに含まれる値のいずれかである必要があるという制約を設けることができます。指定された値がリストに含まれていない場合、argparseはエラーを表示します。- 例:
parser.add_argument('--mode', choices=['read', 'write', 'append'], help='処理モードを指定します。')
-
nargsで引数の個数を指定nargs引数を使うと、オプション引数が受け取る値の個数を制御できます。nargs='?': 0個または1個の値を受け取ります。値が指定されなかった場合のデフォルト値 (defaultで指定) と、値が指定されたがそれがパーサーにとって不明な場合に使われるデフォルト値 (constで指定) を区別できます。nargs='*': 0個以上の値を受け取ります。値はリストとして取得されます。nargs='+': 1個以上の値を受け取ります。値はリストとして取得されます。リストは空になりません。nargs='N'(Nは整数): 正確にN個の値を受け取ります。値はリストとして取得されます。
- 例:
parser.add_argument('--files', nargs='+', help='処理するファイル名を1つ以上指定') nargsは位置引数に対しても使用できます。例えば、複数の入力ファイルを指定させたい場合に便利です。例:parser.add_argument('input_files', nargs='+', help='入力ファイル (複数指定可能)')
ヘルプメッセージのカスタマイズ
argparse のヘルプメッセージは非常に便利ですが、その表示をカスタマイズすることも可能です。
-
description,epilogArgumentParserコンストラクタのdescription引数で、プログラム全体の簡単な説明を指定できます(ヘルプメッセージの上部に表示されます)。epilog引数で、ヘルプメッセージの下部に表示する追加情報を指定できます(例: 使用例など)。
-
formatter_class- ヘルプメッセージの整形方法を制御します。デフォルトでは、長い
helpメッセージは自動的に折り返されます。この自動折り返しを無効にしたい場合などに使います。 - 例:
formatter_class=argparse.RawTextHelpFormatterを指定すると、改行を含むdescriptionやepilog、helpメッセージがそのまま表示されます。 - 例:
formatter_class=argparse.ArgumentDefaultsHelpFormatterを指定すると、ヘルプメッセージに各引数のデフォルト値が表示されるようになります。
- ヘルプメッセージの整形方法を制御します。デフォルトでは、長い
“`python
import argparse
parser = argparse.ArgumentParser(
description=”’\
ファイル処理ユーティリティ
指定されたファイルを読み込み、加工して出力します。
複数のファイルや異なる処理モードに対応しています。”’,
epilog=”’\
使用例:
%(prog)s –mode read input.txt
%(prog)s –mode write output.csv –force
%(prog)s –mode process –count 10 data*.log”’,
formatter_class=argparse.RawTextHelpFormatter # description/epilog の改行を有効にする
)
parser.add_argument(
‘–mode’,
choices=[‘read’, ‘write’, ‘process’],
required=True,
help=’処理モードを指定 (read, write, process)’
)
parser.add_argument(
‘input_files’,
nargs=’+’, # 1つ以上のファイル名を受け取る
help=’処理対象となるファイル名 (複数可)’
)
parser.add_argument(
‘–count’,
type=int,
default=1,
help=’処理回数を指定 (デフォルト: %(default)s)’ # %(default)s でデフォルト値を表示
)
parser.add_argument(
‘–force’,
action=’store_true’,
help=’強制的に実行します’
)
args = parser.parse_args()
print(f”処理モード: {args.mode}”)
print(f”対象ファイル: {args.input_files}”) # nargs=’+’ なのでリスト
print(f”処理回数: {args.count}”)
print(f”強制モード: {args.force}”)
“`
ヘルプメッセージ (python your_script.py -h) を確認すると、description や epilog が指定通りに表示され、%(default)s の部分がデフォルト値に置き換わっていることがわかります。
サブコマンド (Sub-commands)
一つのスクリプトで複数の異なる機能を持ち、それぞれ異なる引数を持つ場合(例: git commit, git push, git pull のようなコマンド)、サブコマンド機能が非常に便利です。argparse はこのサブコマンドを簡単に実装できます。
add_subparsers() メソッドを使ってサブコマンドパーサーを作成し、それぞれのサブコマンドに対して独自の引数を定義します。
“`python
subcommand_example.py
import argparse
parser = argparse.ArgumentParser(description=’サブコマンドの例’)
サブコマンドパーサーを作成
subparsers = parser.add_subparsers(dest=’command’, help=’実行するコマンド’)
dest=’command’ により、実行されたサブコマンド名が args.command に格納される
‘create’ サブコマンドを定義
create_parser = subparsers.add_parser(‘create’, help=’新しいアイテムを作成’)
create_parser.add_argument(‘item_name’, help=’作成するアイテムの名前’)
create_parser.add_argument(‘–type’, default=’file’, help=’アイテムのタイプ (デフォルト: file)’)
‘delete’ サブコマンドを定義
delete_parser = subparsers.add_parser(‘delete’, help=’アイテムを削除’)
delete_parser.add_argument(‘item_id’, type=int, help=’削除するアイテムのID’)
delete_parser.add_argument(‘–force’, action=’store_true’, help=’強制削除’)
‘list’ サブコマンドを定義
list_parser = subparsers.add_parser(‘list’, help=’アイテム一覧を表示’)
list_parser.add_argument(‘–long’, ‘-l’, action=’store_true’, help=’詳細表示’)
args = parser.parse_args()
実行されたサブコマンドによって処理を分岐
if args.command == ‘create’:
print(f”コマンド: create”)
print(f” アイテム名: {args.item_name}”)
print(f” タイプ: {args.type}”)
elif args.command == ‘delete’:
print(f”コマンド: delete”)
print(f” アイテムID: {args.item_id}”)
print(f” 強制削除: {args.force}”)
elif args.command == ‘list’:
print(f”コマンド: list”)
print(f” 詳細表示: {args.long}”)
else:
# parse_args() が成功した場合、args.command は必ずサブコマンド名のいずれかになるはずですが、念のため
print(“コマンドが指定されていません。-h でヘルプを確認してください。”)
“`
実行例:
bash
python subcommand_example.py -h
出力 (ヘルプメッセージ):
“`
usage: subcommand_example.py [-h] {create,delete,list} …
サブコマンドの例
positional arguments:
{create,delete,list} 実行するコマンド
create 新しいアイテムを作成
delete アイテムを削除
list アイテム一覧を表示
options:
-h, –help show this help message and exit
“`
サブコマンドごとのヘルプ:
bash
python subcommand_example.py create -h
出力:
“`
usage: subcommand_example.py create [-h] [–type TYPE] item_name
新しいアイテムを作成
positional arguments:
item_name 作成するアイテムの名前
options:
-h, –help show this help message and exit
–type TYPE アイテムのタイプ (デフォルト: file)
“`
サブコマンドを指定して実行:
bash
python subcommand_example.py create my_document --type folder
出力:
コマンド: create
アイテム名: my_document
タイプ: folder
bash
python subcommand_example.py delete 123 --force
出力:
コマンド: delete
アイテムID: 123
強制削除: True
bash
python subcommand_example.py list -l
出力:
コマンド: list
詳細表示: True
サブコマンド機能を使うことで、一つのスクリプトで複数の機能を分かりやすく提供できます。
引数のグループ化 (Argument Groups)
多数のオプション引数がある場合、ヘルプメッセージが見にくくなることがあります。add_argument_group() を使うと、関連する引数をグループ化してヘルプメッセージを見やすく整理できます。
“`python
import argparse
parser = argparse.ArgumentParser(description=’引数グループ化の例’)
必須オプションのグループ
required_group = parser.add_argument_group(‘必須オプション’, ‘これらのオプションは必須です。’)
required_group.add_argument(‘–config’, required=True, help=’設定ファイルのパス’)
required_group.add_argument(‘–output’, required=True, help=’結果出力ディレクトリ’)
オプション設定のグループ
optional_group = parser.add_argument_group(‘オプション設定’, ‘追加の設定項目です。’)
optional_group.add_argument(‘–threshold’, type=float, default=0.5, help=’閾値’)
optional_group.add_argument(‘–log-level’, choices=[‘INFO’, ‘DEBUG’], default=’INFO’, help=’ログレベル’)
args = parser.parse_args()
print(f”Configファイル: {args.config}”)
print(f”出力ディレクトリ: {args.output}”)
print(f”閾値: {args.threshold}”)
print(f”ログレベル: {args.log_level}”)
“`
ヘルプメッセージ (python your_script.py -h) を実行すると、定義したグループごとに引数がまとめて表示されることがわかります。
カスタムアクション (Custom Actions)
より高度な使い方として、argparse.Action クラスを継承して独自の action を定義することも可能です。これにより、引数の値を特定の形式で処理したり、引数が指定されたときに特定の関数を呼び出したりといったカスタムの動作をさせることができます。これは少し発展的な内容なので、ここでは概念の説明に留めますが、標準の action (store, store_true, appendなど) だけでは表現できない複雑な挙動を実現したい場合に役立ちます。
ファイルからの引数読み込み (@ プレフィックス)
argparse は、ファイルから引数を読み込む機能も持っています。ArgumentParser を作成する際に fromfile_prefix_chars 引数に ‘@’ などの文字を指定しておくと、コマンドラインで @ファイル名 のように指定された場合、そのファイルの内容を行ごとに読み込み、それぞれを引数として扱います。長い引数リストを何度も指定する場合などに便利です。
ファイル (args.txt) の内容:
--input-file
data/input.txt
--output
results/output.csv
--count
100
--verbose
スクリプト (read_from_file.py):
“`python
import argparse
fromfile_prefix_chars=’@’ を指定
parser = argparse.ArgumentParser(
description=’ファイルから引数を読み込む例’,
fromfile_prefix_chars=’@’
)
parser.add_argument(‘–input-file’, help=’入力ファイル’)
parser.add_argument(‘–output’, help=’出力ファイル’)
parser.add_argument(‘–count’, type=int, default=1, help=’回数’)
parser.add_argument(‘–verbose’, action=’store_true’, help=’詳細’)
args = parser.parse_args()
print(f”入力ファイル: {args.input_file}”)
print(f”出力ファイル: {args.output}”)
print(f”回数: {args.count}”)
print(f”詳細モード: {args.verbose}”)
“`
実行例:
bash
python read_from_file.py @args.txt
出力:
入力ファイル: data/input.txt
出力ファイル: results/output.csv
回数: 100
詳細モード: True
ファイルに記述した引数が正しく解析されていることがわかります。
エラーハンドリングとベストプラクティス
argparse を使うことで多くのエラーハンドリングが自動化されますが、いくつかの点に注意することで、より堅牢でユーザーフレンドリーなスクリプトを作成できます。
argparseによる自動エラーメッセージ:argparseは、必須引数が不足している、型変換に失敗した、choicesで指定された値以外が渡された、といったエラーを検知すると、適切なエラーメッセージを標準エラー出力に表示し、sys.exit(2)(通常は引数解析エラーを示す終了コード)でプログラムを終了します。これにより、開発者はこれらの基本的なエラーチェックを自分で書く手間が省けます。sys.exit()と終了コード: コマンドラインツールでは、プログラムの終了時に「終了コード」(または終了ステータス)を返すのが一般的な作法です。終了コード0は正常終了、非ゼロの値(慣習的には1が一般的なエラー、2がコマンドライン引数エラーなど)は異常終了を示します。sys.exit(exit_code)を使うことで、任意の終了コードでプログラムを終了できます。argparseは引数解析エラー時に自動でsys.exit(2)を呼び出しますが、ファイルが見つからないなどのプログラム固有のエラーが発生した場合には、自分でsys.exit(1)などを呼び出すと良いでしょう。- 引数解析はスクリプトの早い段階で行う: コマンドライン引数はプログラム全体の挙動に影響することが多いので、スクリプトの冒頭で
parser.parse_args()を実行し、その結果を元に後続の処理を分岐させるのが良いプラクティスです。これにより、不正な引数が指定された場合に、余計なリソースを消費したり、予期しない副作用が発生したりする前にプログラムを終了させることができます。 - ヘルプメッセージを分かりやすく書くことの重要性:
add_argument()のhelp引数やArgumentParserのdescription,epilogを適切に記述することで、ユーザーは-hオプションを実行するだけでプログラムの使い方を理解できます。専門用語は避け、具体的な使用例を含めるなど、ユーザーの視点に立って記述することが重要です。%(default)sや%(prog)sのような書式指定子を活用するのも良い方法です。
まとめ
この記事では、Pythonにおけるコマンドライン引数の扱いについて、最も基本的な sys.argv から、強力な標準ライブラリ argparse の詳細な使い方までを解説しました。
sys.argv: Pythonスクリプトに渡された引数を文字列のリストとして取得する最も簡単な方法です。リストの最初の要素はスクリプト名自身です。シンプルですが、引数の区別、型変換、エラーチェックなどをすべて手動で行う必要があるため、複雑な引数処理には向いていません。argparse: コマンドライン引数処理のための標準ライブラリです。引数の定義、パース、型変換、デフォルト値、必須/オプションの区別、自動ヘルプメッセージ生成、エラーチェックなどを自動で行ってくれます。位置引数、オプション引数、フラグ、複数の値を受け取る引数、サブコマンドなど、柔軟な引数構成に対応できます。ほとんどのユースケースでsys.argvよりもargparseを使うべきです。
コマンドライン引数を使いこなすことで、あなたのPythonスクリプトはより柔軟で、再利用性が高く、自動化に適したものになります。設定ファイルを使ったり、対話的に入力を求めたりする方法もありますが、コマンドライン引数は特にバッチ処理やシェルスクリプトからの呼び出しにおいて強力なインターフェースとなります。
特に argparse は、標準ライブラリでありながら非常に高機能です。この記事で紹介した基本的な使い方から、nargs や choices、サブコマンドといった応用的な機能までを理解し、あなたのスクリプトに最適な引数処理を実装してください。
これで、あなたはPythonコマンドライン引数の「超基本」を理解し、さらに argparse という強力な武器を手に入れました。ぜひ実際にコードを書いて、コマンドライン引数の便利さを体験してみてください。