コマンドライン引数
初回公開:2019/02/09
最終更新:未
【 目次 】
windows10 -python3で検証
sys.argv
pythonでコマンドライン引数にアクセスするにはsysモジュールのargvを使用する。
- 29.1. sys — システムパラメータと関数 — Python 3.6.5 ドキュメント
Pythonスクリプトに渡されたコマンドライン引数のリスト。
argv[0] はスクリプトの名前となりますが、フルパス名かどうかは、OSによって異なります。
コマンドライン引数に -c を付けて Pythonを起動した場合、 argv[0] は文字列 '-c' となります。
スクリプト名なしでPythonを起動した場合、 argv[0] は空文字列になります。
argv_test.py
import sys print("sys.argv=",sys.argv) print("sys.argv=の型は",type(sys.argv)) # list型 print("引数の数(実際には一つ多くなる)=",len(sys.argv)) for argi in sys.argv: print(argi)
実行結果
C:\arg_test> python argv_test.py -a -b xxx sys.argv= ['argv_test.py', '-a', '-b', 'xxx'] sys.argv=の型は <class 'list'> 引数の数(実際には一つ多くなる)= 4 argv_test.py -a -b xxx
ArgumentParser (argparse)
sys.argvを使う方法はシンプルで解りやすいのだが、UNIX流のコマンドライン引数を簡単に実装したい場合には、Pythonの標準ライブラリであるArgumentParserを使うのが便利である。
公式ドキュメントの「チュートリアル」は
公式ドキュメントの「argparseモジュールのドキュメント」は
他のサイトの参考記事
- 【Python】コマンドライン引数を解析する(argparseの利用) - Flat Leon Works
- ライブラリ: argparse - Life with Python
- pythonでコマンドライン引数を使うサンプル - Qiita
- argparse - Qiita
- Python argparseの使い方 - Qiita
基礎
(ほとんど)何もしない、とても簡単な例
チュートリアルより引用
ArgumentParserモジュールを使う基本形は以下のコードになる。
argparse_sample0.py
import argparse parser = argparse.ArgumentParser() parser.parse_args()
python argparse_sample0.py -h
または
python argparse_sample0.py --help
実行結果
usage: argparse_sample0.py [-h] optional arguments: -h, --help show this help message and exit
上記のコードを使う事で、 -h, --helpオプションが自動的に実装される。
コマンドライン引数は、位置引数とOptional引数とがある。
そして、Optional引数には値を指定するOptional引数もある。
これらの指定方法についてみていく事にする。
位置引数
位置引数は引数を指定する位置によってその意味が決定される。
また、位置引数は省略できない必須の引数となる。
但し、add_argumentに名前付き引数default(後述)を指定すると位置引数は省略可能となる場合がある。
位置引数を一つ指定
以下の例は位置引数を一つ指定するプログラムの例
argparse_sample1.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("echo") args = parser.parse_args() print(args.echo)
引数を指定しないでプログラムを実行
python argparse_sample1.py
位置引数は必須の引数なので以下のようなエラーになる。
実行結果
usage: argparse_sample1.py [-h] echo argparse_sample1.py: error: the following arguments are required: echo
引数を一つ指定すると
python argparse_sample1.py xxx
指定した引数が表示される
実行結果
xxx
引数を余分に指定すると
python argparse_sample1.py xxx yyy
エラーになる。
実行結果
usage: argparse_sample1.py [-h] echo argparse_sample1.py: error: unrecognized arguments: yyy
コマンドライン引数にヘルプメッセージを指定する
位置引数や後述するOptional引数には、
add_argumentメソッドの名前付き引数helpに引数のヘルプメッセージを指定する事ができる。
argparse_sample2.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("echo", help="echo 引数を表示") args = parser.parse_args() print(args.echo)
python argparse_sample2.py -h
実行結果
usage: argparse_sample2.py [-h] echo positional arguments: echo echo 引数を表示 optional arguments: -h, --help show this help message and exit
位置引数の複数指定と位置引数の順序
位置引数はadd_argumentメソッドで指定された順に引数の順番が決定されるようだ。
以下の例は位置引数を3つ指定する例である。
argparse_sample3.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("pos1", help="位置引数1") parser.add_argument("pos2", help="位置引数2") parser.add_argument("pos3", help="位置引数3") args = parser.parse_args() print("pos1={} , pos2={} , pos3={}".format(args.pos1, args.pos2, args.pos3))
python argparse_sample3.py xxx yyy zzz
実行結果
pos1=xxx , pos2=yyy , pos3=zzz
helpオプションを指定して実行すると
python argparse_sample3.py -h
実行結果
usage: argparse_sample3.py [-h] pos1 pos2 pos3 positional arguments: pos1 位置引数1 pos2 位置引数2 pos3 位置引数3 optional arguments: -h, --help show this help message and exit
デフォルト値の指定と位置引数の省略
add_argumentメソッドに名前付き引数defaultを指定する事で引数のデフォルト値を指定する事ができる。
add_argumentメソッドに名前付き引数nargs が ?
か *
を指定すると、位置引数では、コマンドライン引数が指定されなかった場合 default の値が使われる。
ここでは、nargsに?
を,defaultにデフォルト値を指定する例を示す。
nargsについては後述。
argparse_sample4.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("pos1", help="位置引数1", nargs='?',default="aaa") parser.add_argument("pos2", help="位置引数2") parser.add_argument("pos3", help="位置引数3", nargs='?',default="ccc") args = parser.parse_args() print("pos1={} , pos2={} , pos3={}".format(args.pos1, args.pos2, args.pos3))
位置引数pos1,pos3はデフォルト値が指定されているので省略可能。
従って、pos2の値のみを指定。
python argparse_sample4.py yyy
実行結果
pos1=aaa , pos2=yyy , pos3=ccc
引数を2つ指定すると、最後の引数pos3のみが省略されたものと解釈される。
python argparse_argparse_sample4.py xxx yyy
実行結果
pos1=xxx , pos2=yyy , pos3=ccc
すべての引数を指定
python argparse_sample4.py xxx yyy zzz
実行結果
pos1=xxx , pos2=yyy , pos3=zzz
引数なしで実行すると
python argparse_sample4.py
位置引数pos2は省略では無いのでエラー
実行結果
usage: argparse_sample4.py [-h] [pos1] pos2 [pos3] argparse_sample3_2.py: error: the following arguments are required: pos2
helpオプションの出力を確認
python argparse_sample4.py -h
pos1とpos3が[]で囲まれているので省略可能な事が確認できる。
実行結果
usage: argparse_sample4.py [-h] [pos1] pos2 [pos3] positional arguments: pos1 位置引数1 pos2 位置引数2 pos3 位置引数3 optional arguments: -h, --help show this help message and exit
複雑な位置引数の場合、引数がどの位置引数に代入されるかをよく考えないと混乱するので注意。
位置引数の指定を省略する事は可能だが、そのような場合は次項のOptional引数を使用した方がわかりやすいように思う。
これに更にnargsによって複数の引数値を持つ引数を考慮すると何が何やら。
Optional引数
位置引数が省略できない必須の引数であるのに対してOptional引数は文字どうり省略可能な引数で、位置引数と異なり引数をどの位置に指定しても良い。
Optional引数には値を指定しない引数と値を指定する引数とがある。
ここでは値を指定しない引数を値無しのOptional引数,値付きのOptional引数と呼ぶことにする。
値を指定するOptional引数
値を指定するOptional引数の例を示す。 add_argumentメソッドの第1引数nameに--が付いている。
argparse_sample5.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("--verbosity", help="出力の詳細度オプション") args = parser.parse_args() if args.verbosity: print("verbosityオプション値",args.verbosity) else: print("verbosityオプション無し") print("args.verbosity=",args.verbosity,type(args.verbosity))
HELPオプションを指定して実行
python argparse_sample5.py -h
実行結果
usage: argparse_sample5.py [-h] [--verbosity VERBOSITY] optional arguments: -h, --help show this help message and exit --verbosity VERBOSITY 出力の詳細度オプション
Optional引数に値を指定
python argparse_sample5.py --verbosity 1
実行結果
verbosityオプション値 1
Optional引数の指定を省略
python argparse_sample5.py
Optional引数を指定しない場合、Optional引数の値はNoneに
実行結果
verbosityオプション無し args.verbosity= None <class 'NoneType'>
最後に、Optional引数に値を指定せずに実行
python argparse_sample5.py --verbosity
引数に値が指定されていないのでエラーに
実行結果
usage: argparse_sample5.py [-h] [--verbosity VERBOSITY] argparse_sample4.py: error: argument --verbosity: expected one argument
短いオプション
通常、オプションOptional引数は、--verbosityのように--をつけて長い文字列を指定するとともに、-vのような短い文字でも使えるように指定する。
これを実現するには、add_argumentメソッドに複数の引数名を指定する。
argparse_sample6.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("-v", "--verbosity", help="出力の詳細度オプション") args = parser.parse_args() if args.verbosity: print("verbosityオプション値",args.verbosity) # print("vオプション値",args.v) else: print("verbosityオプション無し")
HELPオプションを指定
python argparse_sample6.py -h
実行結果
usage: argparse_sample6.py [-h] [-v VERBOSITY] optional arguments: -h, --help show this help message and exit -v VERBOSITY, --verbosity VERBOSITY 出力の詳細度オプション
短いオプションを指定
python argparse_sample6.py -v 1
実行結果
verbosityオプション値 1
長いオプションを指定
python argparse_sample6.py --verbosity 1
実行結果
verbosityオプション値 1
やりがちなことだが、オプション値にアクセスしようとしてargs.vの値を参照しても値はセットされていない。
print("vオプション値",args.v)
python argparse_sample6.py -v 1
実行結果
verbosityオプション値 1 Traceback (most recent call last): File "argparse_sample6.py", line 9, in <module> print("vオプション値",args.v) AttributeError: 'Namespace' object has no attribute 'v'
値指定無しのOptional引数
add_argumentメソッドの名前付き引数actionにstore_true
を指定すると値指定無しのOptional引数を意味する事になる。
argparse_sample7.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("-v", "--verbose", help="出力の詳細オプション", action="store_true") args = parser.parse_args() if args.verbose: print("verboseオプションあり") else: print("verboseオプション無し") print("args.verbose=",args.verbose,type(args.verbose))
英語の微妙な単語の意味合いで、前項のverbosityオプションがverboseオプションに変更されている点に注意。
引数付きでverboseオプションを指定
python argparse_sample7.py -v 1
値指定無しのOptional引数なのでエラー
実行結果
usage: argparse_sample7.py [-h] [-v] argparse_sample7.py: error: unrecognized arguments: 1
HELPメッセージを確認
python argparse_sample7.py -h
-v, --verboseには値指定が無い事がわかる。
実行結果
usage: argparse_sample7.py [-h] [-v] optional arguments: -h, --help show this help message and exit -v, --verbose 出力の詳細オプション
python argparse_sample7.py -v
または
python argparse_sample7.py --verbose
を実行
実行結果
verboseオプションあり args.verbose= True <class 'bool'>
verboseオプションの指定を省略
python argparse_sample7.py
実行結果
verboseオプション無し args.verbose= False <class 'bool'>
値指定無しのOptional引数の値の型はbool型になる事に注意。
名前付き引数actionにはstore_false
を指定する事もできて、その場合には論理が反転して、Optional引数ありの場合にFalseに,無しの場合にTrueになる。
Optional引数へのデフォルト値の指定
位置引数と同様、add_argumentメソッドに名前付き引数defaultを指定する事で、Optional引数もデフォルト値の指定が可能
argparse_sample8.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("-d", default="デフォルト",help="デフォルト値付きのオプション") args = parser.parse_args() print("dオプションの値",args.d)
引数を指定しないで実行
python argparse_sample8.py
デフォルト値が表示される
実行結果
dオプションの値 デフォルト
python argparse_sample8.py -d 新しい値
実行結果
dオプションの値 新しい値
HELPオプションの出力を確認
python argparse_sample8.py -h
実行結果
usage: argparse_sample8.py [-h] [-d D] optional arguments: -h, --help show this help message and exit -d D デフォルト値付きのオプション
競合するオプション
add_mutually_exclusive_groupメソッドを使うと、互いに競合するオプション(同時には指定できない相互に排他的なオプション)を指定することができる。
ここでは互いに競合する--unixオプションと--windowsオプションを指定する例を示す。
argparse_sample9.py
import argparse parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group() group.add_argument("-u", "--unix", action="store_true") group.add_argument("-w", "--windows", action="store_true") args = parser.parse_args() if args.unix: print("osはunixです") elif args.windows: print("osはwindowsです") else: print("osは未指定です")
実行結果
C:\arg_test> python argparse_sample9.py -h usage: argparse_sample9.py [-h] [-u | -w] optional arguments: -h, --help show this help message and exit -u, --unix -w, --windows C:\arg_test> python argparse_sample9.py -u osはunixです C:\arg_test> python argparse_sample9.py -w osはwindowsです C:\arg_test> python argparse_sample9.py osは未指定です C:\arg_test> python argparse_sample9.py -u -w usage: argparse_sample9.py [-h] [-u | -w] argparse_sample9.py: error: argument -w/--windows: not allowed with argument -u/--unix
位置引数とOptional引数の指定した時の引数の位置関係
Optional引数は引数をどの位置に指定しても良いが、位置引数の場合は引数の位置が固定となる。
位置引数とOptional引数とが複雑に混在した場合、引数の値がどの引数に対応するかに注意。
3つの位置引数と3つのOptional引数を混在させた例を示す。
argparse_sample10.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("pos1", help="位置引数1") parser.add_argument("pos2", help="位置引数2") parser.add_argument("pos3", help="位置引数3") parser.add_argument("-o1", "--option1", help="値指定無しのOptional引数1", action="store_true") parser.add_argument("-o2", "--option2" , help="値指定無しのOptional引数2", action="store_true") parser.add_argument("-ov", "--optionValue", help="引数を値無しのOptional引数") args = parser.parse_args() print("pos1={} , pos2={} , pos3={}".format(args.pos1, args.pos2, args.pos3)) print("option1={} , option2={} , optionValue={}".format(args.option1, args.option2, args.optionValue))
まず、HELPメッセージを確認
python argparse_sample10.py -h
実行結果
usage: argparse_sample10.py [-h] [-o1] [-o2] [-ov OPTIONVALUE] pos1 pos2 pos3 positional arguments: pos1 位置引数1 pos2 位置引数2 pos3 位置引数3 optional arguments: -h, --help show this help message and exit -o1, --option1 値指定無しのOptional引数1 -o2, --option2 値指定無しのOptional引数2 -ov OPTIONVALUE, --optionValue OPTIONVALUE 引数を値無しのOptional引数
python argparse_sample10.py -o2 xxx -ov opton_value yyy -o1 zzz
実行結果
pos1=xxx , pos2=yyy , pos3=zzz option1=True , option2=True , optionValue=opton_value
例は示さないが、これに更に省略可能な位置引数がからんでくると更に複雑に。
choices - 指定できる値を限定する
add_argumentメソッドに名前付き引数choicesを指定すると
引数に指定できる値を限定する事ができる。
位置引数にchoicesを設定
位置引数の例を以下に示す。
argparse_sample11.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("pos", choices=["勝ち", "負け","引き分け"], help="結果") args = parser.parse_args() print("posの値",args.pos)
「勝ち」,「負け」,「引き分け」以外の値「勝利」を指定するとエラーになる事が確認できる
実行結果
C:\arg_test> python argparse_sample11.py -h usage: argparse_sample11.py [-h] {勝ち,負け,引き分け} positional arguments: {勝ち,負け,引き分け} 結果 optional arguments: -h, --help show this help message and exit C:\arg_test> python argparse_sample11.py 勝ち posの値 勝ち C:\arg_test> python argparse_sample11.py 負け posの値 負け C:\arg_test> python argparse_sample11.py 引き分け posの値 引き分け C:\arg_test> python argparse_sample11.py 勝利 usage: argparse_sample11.py [-h] {勝ち,負け,引き分け} argparse_sample11.py: error: argument pos: invalid choice: '勝利' (choose from ' 勝ち', '負け', '引き分け')
Optional引数にchoicesを設定
Optional引数の例を以下に示す。
argparse_sample12.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("-r", "--result_option", choices=["勝ち", "負け","引き分け"], help="結果オプション") args = parser.parse_args() if args.result_option: print("result_optionの値",args.result_option) else: print("result_optionが指定されていない")
実行結果
C:\arg_test> python argparse_sample12.py -h usage: argparse_sample12.py [-h] [-r {勝ち,負け,引き分け}] optional arguments: -h, --help show this help message and exit -r {勝ち,負け,引き分け}, --result_option {勝ち,負け,引き分け} 結果オプション C:\arg_test> python argparse_sample12.py -r 勝ち result_optionの値 勝ち C:\arg_test> python argparse_sample12.py -r 負け result_optionの値 負け C:\arg_test> python argparse_sample12.py -r 引き分け result_optionの値 引き分け C:\arg_test> python argparse_sample12.py -r 勝利 usage: argparse_sample12.py [-h] [-r {勝ち,負け,引き分け}] argparse_sample12.py: error: argument -r/--result_option: invalid choice: '勝利' (choose from '勝ち', '負け', '引き分け')
in演算をサポートしている任意のオブジェクトを choicesに設定
choicesには固定の値のリストだけではなく、range型等のin演算をサポートしている任意のオブジェクトを指定する事ができる。
- argparse --- コマンドラインオプション、引数、サブコマンドのパーサー — Python 3.7.2 ドキュメント
in 演算をサポートしている任意のオブジェクトを choices に渡すことができます。すなわち、dict 、 set、カスタムコンテナーなどはすべてサポートされています。
in演算子については
in演算をサポートしている任意のオブジェクトをchoicesに指定する例を以下に示す。
argparse_sample13.py
import argparse parser = argparse.ArgumentParser() parser.add_argument('-i', type=int, choices=range(1, 4),help="1~3の整数値を指定") parser.add_argument("-c", type=str, choices=list("abc"),help="a,b,cのいずれかの文字を指定") d={'jack': 4098, 'sape': 413} parser.add_argument("-k", type=str, choices=d,help="辞書dのキーを指定") parser.add_argument("-v", type=int, choices=d.values(),help="辞書dの値を指定") def myfunc(d): l=list() for key in d: l.append("{}-{}".format(key, d[key])) return l parser.add_argument("-kv", type=str, choices=myfunc(d),help="辞書dのkey-valueを指定") args = parser.parse_args() # -iで指定された整数値を出力 if args.i: print("i=",args.i) # -cで指定された文字を出力 if args.c: print("c=",args.c) # キーから辞書dの値を出力 if args.k: print("value=",d[args.k]) # 値から辞書dのキーを出力 if args.v: for key in d: if d[key]==args.v: print("key=",key) # キーと値を出力 if args.kv: kv=args.kv.split("-") print("key={},value={}".format(kv[0],kv[1]))
add_argumentの名前付き引数typeについては次項で述べるが引数値の型を指定する。
-iオプションに1〜3の整数値を,
-cオプションにa,b,cのいずれかの文字を,
-kオプションに辞書dのキーを,
-vオプションに辞書dの値を,
-kvオプションに辞書dのキーと値を-でつなげた文字を
指定する事を選択させられる事になる。
実行結果
C:\arg_test> python argparse_sample13.py -h usage: argparse_sample13.py [-h] [-i {1,2,3}] [-c {a,b,c}] [-k {jack,sape}] [-v {4098,413}] [-kv {jack-4098,sape-413}] optional arguments: -h, --help show this help message and exit -i {1,2,3} 1〜3の整数値を指定 -c {a,b,c} a,b,cのいずれかの文字を指定 -k {jack,sape} 辞書dのキーを指定 -v {4098,413} 辞書dの値を指定 -kv {jack-4098,sape-413} 辞書dのkey-valueを指定 C:\arg_test> python argparse_sample13.py -i 2 -c a -k jack -v 413 -kv sape-413 i= 2 c= a value= 4098 key= sape key=sape,value=413
無限個の許容範囲を指定
choicesには無限個の許容範囲を指定する方法もあるようで、
上記のサイトに載っているサンプルコードsample3.pyの最後に
args = parser.parse_args()
を追加してhelpメッセージを表示してみると
実行結果
c\arg_test> python sample3.py -h usage: sample3.py [-h] [-s {integer, 2 <= x <= +inf}] LightsOut Solver optional arguments: -h, --help show this help message and exit -s {integer, 2 <= x <= +inf} LightsOut Size
引数の型 typeを使えばどんな型の引数も受け取れる
typeに引数の型指定
これまで、引数の値の型は基本的に文字列として受け取っていたが、
add_argumentメソッドに名前付き引数typeを使って引数の値の型を指定して受け取る事もできる。
argparse_sample14.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("-s", type=str, help="str型の値を指定") parser.add_argument("-i", type=int, help="int型の値を指定") parser.add_argument("-f", type=float, help="float型の値を指定") parser.add_argument("-t", type=tuple, help="タプル型の値を指定") args = parser.parse_args() if args.s: print(args.s,type(args.s)) if args.i: print(args.i,type(args.i)) if args.f: print(args.f,type(args.f)) if args.t: print(args.t,type(args.t))
実行結果
C:\arg_test> python argparse_sample14.py -s xxx -i 123 -f 1e-3 -t "(5, 99.9, 'abc')" xxx <class 'str'> 123 <class 'int'> 0.001 <class 'float'> ('(', '5', ',', ' ', '9', '9', '.', '9', ',', ' ', "'", 'a', 'b', 'c', "'", ')') <class 'tuple'>
type=tuple
として受け取った結果の型は確かにtuple型ではあるが、指定した意図に反して1文字ずつの要素として格納されている。
list型についても同様である。
また、注意が必要な点として、タプル型の値を指定する時に引用符で囲っている事。
コマンドライン引数では値の途中でスペーズがあると引数の区切りとみなされてしまう。
引用符で囲わないと次のようなエラーになってしまう。
実行結果
C:\arg_test> python argparse_sample14.py -t (5, 99.9, 'abc') usage: argparse_sample14.py [-h] [-s S] [-i I] [-f F] [-t T] argparse_sample14.py: error: unrecognized arguments: 99.9, 'abc')
ブール値を扱うときにも注意
type=dictでは辞書型の値を受け取れない
辞書型の値を引数として受け取ろうとして以下のようなコードを記述してもエラーになってしまう。
argparse_sample15.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("-d", type=dict, help="辞書型の値を指定") args = parser.parse_args() if args.d: print(args.d,type(args.d))
実行結果
C:\arg_test> python C:\arg_test> python argparse_sample15.py -d {'jack': 4098, 'sape': 413 usage: argparse_sample15.py [-h] [-d D] argparse_sample15.py: error: unrecognized arguments: 4098, 'sape': 4139}
type キーワード引数により型チェックと型変換を行うことができます。一般的なビルトインデータ型や関数を type 引数の値として直接指定できます:
…
type= には1つの文字列を引数に受け取って変換結果を返すような任意の呼び出し可能オブジェクトを渡すことができます:
typeに渡せる型というのは、pythonのすべての組み込み型を指定できるわけだは無く、1つの文字列を引数にもつ事ができるコンストラクタを持つ型という事になる。
辞書型のオブジェクトを生成しようとして、以下のコードを実行してもエラーになってしまう。
辞書型は1つの文字列を引数もつコンストラクタが存在しないため。
d=dict("{'jack': 4098, 'sape': 4139}")
実行結果
ValueError: dictionary update sequence element #0 has length 1; 2 is required
では、辞書型の引数値を渡す事はできないのだろうか?
また、tupleやlistk型の値を意図したとおりに受け取るにはどうしたら?
それに対する私の解決策は後で述べる事にする。
typeに関数やクラスを指定 -
typeには1つの文字列を引数に持つ任意の関数やクラス(のコンストラクタ)を指定できる
typeには組み込み型だけでなく「1つの文字列を引数に受け取って変換結果を返すような任意の呼び出し可能オブジェクト」を渡すことができる。
つまり、1つの文字列を引数に持つ関数やクラスのコンストラクタを指定する事もできる事になる。
以下のコードは、文字列を小文字に変換するmyfuncという関数を定義してtype引数に指定する事でコマンドライン引数値を小文字に変換するとともに、コマンドライン引数値よりユーザー定義のクラスのオブジェクトを生成する例である。
argparse_sample16.py
import argparse parser = argparse.ArgumentParser() def myfunc(str_arg): return str_arg.lower() parser.add_argument("-l", type=myfunc, help="文字列の値を小文字に変換") class Person(object): def __init__(self,name): self.name=name parser.add_argument("-p", type=Person, help="Personクラスのインスタンスを生成") args = parser.parse_args() if args.l: print(args.l,type(args.l)) if args.p: print(args.p.name,type(args.p))
実行結果
C:\arg_test> python argparse_sample16.py -l XXX -p 愚鈍人 xxx <class 'str'> 愚鈍人 <class '__main__.Person'>
任意の型や任意の式の結果を受け取る
typeに1つの文字列を引数に持つ任意の関数やクラス(のコンストラクタ)を指定できる事を利用すると、コマンドライン引数値に1個の値を受け取る任意の型やPythonの構文で許される任意の式を指定する事ができる。
typeに変換関数を指定できる事を利用すれは、念願の辞書型(やtuple型,list型)だけでなく任意の型や任意の式の結果を受け取る事が可能になる。
argparse_sample17.py
class Person: def __init__(self,name,age): self.name=name self.age=age import argparse parser = argparse.ArgumentParser() def myfunc(str_arg): try: any_obj=eval(str_arg) except: raise argparse.ArgumentTypeError("--anytype:pythonでは評価できない式です",str_arg) return any_obj parser.add_argument("--anytype", type=myfunc, help="任意の型や式を指定") args = parser.parse_args() if args.anytype: print(args.anytype,type(args.anytype))
以下の実行結果はコマンドライン引数に辞書型の値やtuple型,list型、ユーザー定義のクラス,加算演算,complex型の値を指定した例である。
実行結果
C:\arg_test> python argparse_sample17.py --anytype "{'jack': 4098, 'sape': 4139}" {'jack': 4098, 'sape': 4139} <class 'dict'> C:\arg_test> python argparse_sample17.py --anytype "(5, 99.9, 'abc')" (5, 99.9, 'abc') <class 'tuple'> C:\arg_test> python argparse_sample17.py --anytype "[5, 99.9, 'abc']" [5, 99.9, 'abc'] <class 'list'> C:\arg_test> python argparse_sample17.py --anytype "Person('愚鈍人', 99)" <__main__.Person object at 0x03E02790> <class '__main__.Person'> C:\arg_test> python argparse_sample17.py --anytype "10+5" 15 <class 'int'> C:\arg_test> python argparse_sample17..py --anytype "10+5j" (10+5j) <class 'complex'>
typeとchoicesを組み合わせる - 大文字小文字を区別しない引数値の実装
コマンドライン引数値はadd_argumentメソッドの名前付き引数typeで指定された呼び出し可能オブジェクトによって変換された後、choices引数によって選別される。
この事を利用すると大文字小文字を区別しない引数値の実装が可能になる。
choices コンテナーに含まれているかどうかのチェックは、type による型変換が実行された後であることに注意してください。
このため、choices に格納するオブジェクトの型は指定された type にマッチしている必要があります:
argparse_sample18.py
import argparse parser = argparse.ArgumentParser() # 大文字を小文字に変換する関数 def myfunc(str_arg): return str_arg.lower() parser.add_argument("-w", type=myfunc, choices=["win32","win64"],help="文字列の値を小文字に変換") args = parser.parse_args() if args.w: print(args.w)
実行結果
C:\arg_test> python argparse_sample18.py -h usage: argparse_sample18.py [-h] [-w {win32,win64}] optional arguments: -h, --help show this help message and exit -w {win32,win64} 文字列の値を小文字に変換 C:\arg_test> python argparse_sample18.py -w WIN32 win32
type引数の指定には「1つの文字列を引数に受け取って変換結果を返すような任意の呼び出し可能オブジェクト」を渡すことができるので、関数myfuncの定義を省略してtype引数に直接ラムダ式lambda s : s.lower()
やあるいはもっと簡潔にstr.lower
指定する事で同じ事が実現できる。
参考記事
ケース情報を失うことを気にするなら、(上記の記事にあるコードを以下に引用。)
import argparse class mylist(list): # list subclass that uses lower() when testing for 'in' def __contains__(self, other): return super(mylist,self).__contains__(other.lower()) choices=mylist(['win64','win32']) parser = argparse.ArgumentParser() parser.add_argument("-p", choices=choices) print(parser.parse_args(["-p", "Win32"]))
nargs - 1つの引数に複数の値を指定
nargsは
ArgumentParser オブジェクトは通常1つのコマンドライン引数を1つのアクションに渡します。nargs キーワード引数は1つのアクションにそれ以外の数のコマンドライン引数を割り当てます。
とあるが、ここではあまり深入りしない。
nargsは引数の数を指定する名前付き引数で、複数の引数値を持つ引数を定義できて,引数値はリストに格納されるようだ
。
また、nargsの値として指定される?
とか +
,*
というのはいわゆるワイルドカードっぽい。
nargsを指定する事で、argparse_sample17.pyのようなコードを使わずともlist型の値を取得する事もできるが、それぞれの要素の型は同じ型であるという制限を受けてしまうようだ。
位置引数の例を示す。 次のコードは3個の整数値よりその合計を求める。
argparse_sample19.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("sum", nargs =3 ,type=int, help="3個の整数を指定") args = parser.parse_args() if args.sum: total=args.sum[0]+args.sum[1]+args.sum[2] print("合計:",total)
実行結果
C:\arg_test> python argparse_sample19.py 3 4 5 合計: 12
Optional引数の例を示す。 次のコードはargparse_sample17.pyを修正して任意の型の値を複数個受け取る。
argparse_sample20.py
class Person: def __init__(self, name, age): self.name = name self.age = age import argparse parser = argparse.ArgumentParser() def myfunc(str_arg): try: any_obj = eval(str_arg) except: raise argparse.ArgumentTypeError("--anytypes:pythonでは評価できない式です", str_arg) return any_obj parser.add_argument("--anytypes", type=myfunc, nargs="*", help="任意の型や式を1個以上指定") args = parser.parse_args() if args.anytypes: for anytype in args.anytypes: print(anytype, type(anytype))
python argparse_sample20.py --anytypes "{'jack': 4098, 'sape': 4139}" "(5, 99.9, 'abc')" "Person('愚鈍人', 99)" "10+5" "10+5j"
実行結果
{'jack': 4098, 'sape': 4139} <class 'dict'> (5, 99.9, 'abc') <class 'tuple'> <__main__.Person object at 0x03E298B0> <class '__main__.Person'> 15 <class 'int'> (10+5j) <class 'complex'>
dest - Optional引数の属性名を変更
引数の属性名は、以下のように決定される。
位置引数のアクションについては、 dest は通常 add_argument() の第一引数として渡します:
...
オプション引数のアクションについては、 dest の値は通常オプション文字列から生成されます。 ArgumentParser は最初の長いオプション文字列を選択し、先頭の -- を除去することで dest の値を生成します。長いオプション文字列が指定されていない場合、最初の短いオプション文字列から先頭の - 文字を除去することで dest を生成します。先頭以外のすべての - 文字は、妥当な属性名になるように _ 文字へ変換されます。
つまり、位置引数の場合は、add_argumentメソッドの第1引数。
そして、Optional引数の場合は最初の長いオプション文字列で、長いオプションが存在しない場合は最初の短いオプション文字列となる。
Optional引数において、add_argumentメソッドの名前付き引数destを指定するとこの属性名を変更する事ができる。
argparse_sample21.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("-o", "--optionlong", dest="other_name", help="dest付きの引数") args = parser.parse_args() if args.other_name: print(args.other_name)
実行結果
C:\arg_test> python argparse_sample21.py -h usage: argparse_sample21.py [-h] [-o OTHER_NAME] optional arguments: -h, --help show this help message and exit -o OTHER_NAME, --optionlong OTHER_NAME dest付きの引数 C:\arg_test> python argparse_sample21.py -o XXX XXX
位置引数の場合には、destを指定するとエラーになってしまう。
metavar - helpに表示される引数の値として示される文字列を指定
add_argumentメソッドの名前付き引数metavarに指定するとhelpに表示される引数の値として示される文字列を変更する事ができる。
argparse_sample22.py
import argparse parser = argparse.ArgumentParser() parser.add_argument("pos1", help="位置引数1") parser.add_argument("pos2", metavar="filename", help="位置引数2") parser.add_argument("--opt1", help="Optional引数1") parser.add_argument("--opt2", type=int, metavar="N", help="Optional引数2") args = parser.parse_args()
実行結果
C:\arg_test> python argparse_sample22.py -h usage: argparse_sample22.py [-h] [--opt1 OPT1] [--opt2 filename] pos1 filename positional arguments: pos1 位置引数1 filename 位置引数2 optional arguments: -h, --help show this help message and exit --opt1 OPT1 Optional引数1 --opt2 filename Optional引数2
metavarに指定した文字列により、ユーザーに変数値としてどんな値を指定すれば良いか知らせる事ができる。
ArgumentParserの引数
ArgumentParserクラスのコンストラクタにはさまざまな引数を渡す事ができる。
以下はその一部を使ってhelpメッセージの表示を変更する例
argparse_sample23.py
import argparse parser = argparse.ArgumentParser( description="description:プログラムの説明", usage="usage:使い方", epilog="epilog:引数のヘルプの後で表示されるテキスト" ) parser.add_argument("pos", help="位置引数") parser.add_argument("--opt", help="Optional引数") args = parser.parse_args()
実行結果
C:\arg_test> python argparse_sample23.py -h usage: usage:使い方 description:プログラムの説明 positional arguments: pos 位置引数 optional arguments: -h, --help show this help message and exit --opt OPT Optional引数 epilog:引数のヘルプの後で表示されるテキスト
雑感
ArgumentParserは便利なモジュールであるが、細かいところまでマスターしようと思うと大変。
一応、ここでまとめた機能だけで充分かな。