argparseモジュールを使い、コマンドラインを通して渡される位置引数/オプション引数を処理する方法を紹介する。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
import argparse
parser = argparse.ArgumentParser(description='add two integers')
parser.add_argument('x', type=int, help='an integer to be added')
parser.add_argument('y', type=int, help='an integer to be added')
args = parser.parse_args()
result = args.x + args.y
print(result)
import argparse
parser = argparse.ArgumentParser(description='add two integers')
#parser.add_argument('-x', type=int)
#parser.add_argument('-y', type=int)
parser.add_argument('-x', type=int, default=0)
parser.add_argument('-y', type=int, default=0)
args = parser.parse_args()
result = args.x + args.y
print(result)
import argparse
parser = argparse.ArgumentParser(description='add two integer')
parser.add_argument('-s', '--switch1', action='store_true')
parser.add_argument('-t', '--switch2', action='store_true')
args = parser.parse_args()
print(f'switch1: {args.switch1}, switch2: {args.switch2}')
if args.switch1:
print('switch1 is on')
else:
print('swithc1 in off')
if args.switch2:
print('switch is on')
else:
print('switch2 is off')
import argparse
parser = argparse.ArgumentParser(description='add 2 integers')
parser.add_argument('--opt1', nargs=2) # --opt1に続けて2つの値を指定
parser.add_argument('--opt2', nargs='?') # --opt2の後に値を1つ指定してもよい
parser.add_argument('--opt3', nargs='*') # --opt3に続けて0個以上の値を指定
parser.add_argument('--opt4', nargs='+') # --opt4に続けて1つ以上の値を指定
parser.add_argument('pos', nargs='*') # 残りは全て位置引数としてposに格納される
args = parser.parse_args()
print(f'args.opt1: {args.opt1}')
print(f'args.opt2: {args.opt2}')
print(f'args.opt3: {args.opt3}')
print(f'args.opt4: {args.opt4}')
print(f'args.pos: {args.pos}')
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('x') # 位置引数はデフォルトで指定が必須
parser.add_argument('y', nargs='*', default=99) # 位置引数だが省略可能
parser.add_argument('-o', '--option', required=True)
args = parser.parse_args()
print(f'args.x: {args.x}, args.y: {args.y}, args.option: {args.option}')
import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
#group = parser.add_mutually_exclusive_group()
group.add_argument('--quiet', action='store_true')
group.add_argument('--verbose', action='store_true')
args = parser.parse_args()
if args.quiet:
print('in quiet mode')
elif args.verbose:
print('in verbose mode')
else:
print('default mode')
Pythonスクリプトに与えるコマンドライン引数の処理には、前回に紹介したsys.argv属性を使えるが、複雑なコマンドライン処理をするならPythonに標準添付のargparseモジュールが便利に使える。
このモジュールの使い方を簡単にまとめると次のようになる。
この流れを表すシンプルな例を以下に示す。
import argparse # argparseモジュールのインポート
parser = argparse.ArgumentParser() # ArgumentParserクラスのインスタンスを生成
parser.add_argument('x', type=int) # コマンドライン引数の解析方法を追加(1)
parser.add_argument('y', type=int) # コマンドライン引数の解析方法を追加(2)
args = parser.parse_args() # コマンドライン引数の解析
result = args.x + args.y # 戻り値に格納された値を使用
print(result)
argparseモジュールをインポートしたら、ArgumentParserクラスのインスタンスを作成しているが、このときには幾つかの引数を指定できる。詳しくはPythonのドキュメント「ArgumentParser オブジェクト」を参照されたい。ここではdescription引数の指定例を以下に示す。
parser = argparse.ArgumentParser(description='add two integers')
このようにすると、Pythonスクリプトの実行時に「-h」「--help」オプションを指定したときに表示されるヘルプメッセージにdescription引数に指定した値が含まれるようになる。
argparseモジュールでは、コマンドライン引数を位置引数とオプション引数の2種類に大別している。上のコードでadd_argumentメソッドを使って追加しているのは2つの位置引数「x」と「y」だ(オプション引数についてはこの後取り上げる)。「type=int」として、それらの型がint(整数)であることも指定されているのが分かる。なお、型を指定しない場合、コマンドライン引数は文字列としてスクリプトに渡される。コマンドライン引数の型がハッキリしているのであれば、type引数に型を指定するようにしよう。
先ほどのdescription引数と同様に、コマンドライン引数の説明がヘルプメッセージに表示されるようにするには、add_argumentメソッド呼び出し時にhelp引数にそのテキストを指定すればよい。
parser.add_argument('x', type=int, help='an integer to be added')
parser.add_argument('y', type=int, help='an integer to be added')
この後、parse_argsメソッドを呼び出すと、スクリプトに与えられたコマンドライン引数をsys.argv属性を介して取得して、それらが解析される。その結果、位置引数xとyに指定された値がその戻り値の中に格納され、引数名と同じ名前の属性としてアクセスできるようになる。上のコードでは、戻り値は変数argsに代入されているので、「args.x」「args.y」のようにして、指定されたデータ型の値(ここではint型)として使用できる。
以下に実行例を幾つか示す(ファイル名は「argtest1.py」とする)。
% python3 argtest1.py
usage: argtest1.py [-h] x y
argtest1.py: error: the following arguments are required: x, y
これはコマンドライン引数を何も指定せずに、スクリプトを実行した結果だ。最初に表示されている「usage」は、このスクリプトの使い方を簡単に説明したもので、argparseモジュールによるものだ。次の行は2つの位置引数が指定されていないために表示されたエラーメッセージとなっている。
argparseモジュールを使っているスクリプトに「-h」「--help」オプションを指定すると、そのスクリプトのヘルプが表示される。以下に例を示す。
usage: argtest1.py [-h] x y
add two integers
positional arguments:
x an integer to be added
y an integer to be added
options:
-h, --help show this help message and exit
上の方にArgumentParserクラスのインスタンス生成時にdescription引数に指定した「add two integers」が表示されているのが分かる。その下には2つの位置引数の説明が、最後にオプション引数の説明が表示される(上の実行例は、先ほど述べたように、add_argumentメソッド呼び出し時にhelp引数に説明のテキストを入れたもの)。
最後に、2つの位置引数を指定してスクリプトを実行した例を示す。
% python3 argtest1.py 10 20
30
上で見た位置引数は基本的には指定が必須のコマンドライン引数となる。これに対して、基本的には指定が必須ではないコマンドライン引数としてオプション引数がある。オプション引数を指定しない場合、その値はNoneとなる。
また、オプション引数には「--オプション引数 値」のように値を指定するものと、「--オプション引数」のように値を指定しないものがある。後者は、スクリプトの振る舞いを変更するためのスイッチやフラグと呼ばれるものだ。まずは前者の使い方を見てみよう。
オプション引数を追加するのにも、add_argumentメソッドを呼び出せばよい。とのときには、最初に指定する変数名をハイフン「-」で始める。以下に例を示す。
import argparse
parser = argparse.ArgumentParser(description='add two integers')
parser.add_argument('-x', type=int)
parser.add_argument('-y', type=int)
#parser.add_argument('-x', type=int, default=0)
#parser.add_argument('-y', type=int, default=0)
args = parser.parse_args()
result = args.x + args.y
print(result)
最初の例とほぼ同じなので、ここではadd_argumentメソッド呼び出しにだけ注目する。上で述べたように、変数名が「-x」「-y」とハイフンで始まっている点に注目しよう。こうすることで、argparseモジュールはこれらがオプション引数であると認識する。最初の2行では、型がintであることのみを指定している。よって、これらを省略した場合、その値はNoneとなる(これも既に述べた通りだ)。
2つのコマンドライン引数を指定せずに実行した例を以下に示す(ファイル名は「argtest2.py」とする)。
% python3 argtest2.py
Traceback (most recent call last):
File "/Users/.../test/argtest2.py", line 10, in <module>
result = args.x + args.y
TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'
オプション引数を指定しなかったのでデフォルト値であるNoneとNoneを加算しようとしてTypeError例外が発生した。このような事態を避けるには、上のスクリプトでコメントアウトしているコードのように、default引数にオプション引数のデフォルト値を指定しておくとよい。
parser.add_argument('-x', type=int, default=0)
parser.add_argument('-y', type=int, default=0)
コメントアウトを入れ替えて、実行した結果を以下に示す。
% python3 argtest2.py
0
今度はデフォルト値が0となったので問題なく計算できた。
値を指定するタイプのオプション引数は、「--オプション引数 値」または「-省略形 値」のように指定する。そのため、位置引数のように渡したい値だけを指定するとエラーとなる。以下はその例だ。
% python3 argtest2.py 10 20
usage: argtest2.py [-h] [-x X] [-y Y]
argtest2.py: error: unrecognized arguments: 10 20
そうではなく、以下のように指定する。
% python3 argtest2.py -x 10 -y 20
30
後に値を続けない「--option」形式のオプションは、スクリプトの動作を変えるようなスイッチあるいはフラグとして使用することが多い。例えば、pythonコマンドに「-V」オプションまたは「--version」オプションを指定すると、そのバージョンを表示して、コマンドの実行が終了する。
このような形のオプションでは、それが指定されたときにはTrue/Falseを保存するようにする。ただし、このときには「type=bool」のようにtype引数を使うのではなく、action引数を使用する。action引数には以下のような値を指定できる(一部を抜粋)。
この他にも、同じオプションが複数回指定された場合にその数をカウントするcountなどもあるが、詳細についてはPythonのドキュメント「action」を参照されたい。
デフォルトでは実行されない処理を、あるオプションが指定されたら実行するようにするならstore_trueを、逆にデフォルトでは実行される処理を抑制するようなオプションであればstore_falseを指定して、スクリプト内ではif文などで処理を分岐するような使い方になるだろう。
以下に使用例を示す。
import argparse
parser = argparse.ArgumentParser(description='add two integer')
parser.add_argument('-s', '--switch1', action='store_true')
parser.add_argument('-t', '--switch2', action='store_true')
args = parser.parse_args()
print(f'switch1: {args.switch1}, switch2: {args.switch2}')
if args.switch1:
print('switch1 is on')
else:
print('swithc1 in off')
if args.switch2:
print('switch is on')
else:
print('switch2 is off')
add_argumentメソッド呼び出しでは、ハイフンが1つで始まる省略形のオプション名と、長いオプション名が指定されている。こうすることで、「-s」と「--switch1」のどちらを使ってもこのオプションを指定できるようになる。actionにはどちらのオプション引数もstore_trueを指定しているので、これらのオプションを指定すると、parse_argsメソッドの戻り値に含まれる、これらに対応する属性(switch1属性とswitch2属性)にはTrueが指定される。
実行例を以下に示す(ファイル名は「argtest3.py」とする)。何も指定せずにスクリプトを実行すると次のようになる。
% python3 argtest3.py
switch1: False, switch2: False
swithc1 in off
switch2 is off
このときには、どちらのオプションも指定されていないので、対応する属性はどちらもFalseとなっている。その後のif文の処理でもelse節のコードが実行されている。
今度は「--switch1」オプションを指定した場合だ。
% python3 argtest3.py --switch1
switch1: True, switch2: False
switch1 is on
switch2 is off
このときには、switch1属性がTrueとなりif文ではif節が実行されている。「--switch2」オプションを指定した場合はその逆になっている。
% python3 argtest3.py --switch2
switch1: False, switch2: True
swithc1 in off
switch is on
最後に、「-s」「-t」という省略形のオプションを指定した例だ。これらのオプション指定も可能なことを確認してほしい。
% python3 argtest3.py -s -t
switch1: True, switch2: True
switch1 is on
switch is on
Copyright© Digital Advantage Corp. All Rights Reserved.