argparseを使ってみた
追記:
t2yさんが翻訳してくださいました。 argparseコマンドラインオプションと引数の解析
python 2.7からコマンドラインの引数を解釈するargparseモジュールが標準で入りました。
従来使われてきたoptparseは廃止されます。ただし、広く使われているところから他の廃止されるモジュールとは異なり消されることはなく、警告も標準では出ません。
optparseからargparseに移行する理由や廃止の進め方はPEP 389に記載されています。
以下にPEP 389の和訳を(訳に自信がない場所がありますが)行ないましたので参考にしてください。
http://www.tdoc.info/PEP-ja/389.html
というわけで、ざっとargparseの使い方を勉強したのでここに公開します。間違ってたらご指摘ください。
なお、ちゃんとしたドキュメントは http://docs.python.org/library/argparse.html にあります。
argparseの大まかな流れ
- 1. parserを作ります
- 2. 解釈する引数を付け加えます
- 3. parseします
- 4. enjoy!
例 その1
# -*- coding: utf-8 -*- import argparse parser = argparse.ArgumentParser(description='簡単な例です') # parserを作る parser.add_argument('bar') # 引数を追加します parser.add_argument('-f', '--foo') # オプションを追加します parser.add_argument('-r', required=True) # このオプションは必須です parser.add_argument('--version', action='version', version='%(prog)s 2.0') # version args = parser.parse_args() # コマンドラインの引数を解釈します print(args)
実行してみましょう。
% python test.py --help usage: test.py [-h] [-f FOO] -r R bar 簡単な例です positional arguments: bar optional arguments: -h, --help show this help message and exit -f FOO, --foo FOO -r R --version show program's version number and exit % python test.py --version test.py 2.0 % python test.py hoge usage: test.py [-h] [-f FOO] -r R bar test.py: error: argument -r is required % python test.py -r Required hoge Namespace(bar='hoge', foo=None, r='Required')
例 その2 ヘルプを出す
import argparse parser = argparse.ArgumentParser() parser.add_argument('--foo', help='foo help') args = parser.parse_args()
add_argumentにhelpを付け加えます。そうすると、--helpを付けて起動するとこのように表示されます。
% python test2.py --help
usage: test2.py [-h] [--foo FOO]
optional arguments:
-h, --help show this help message and exit
--foo FOO foo help
例 その3 いろいろな変数指定
add_argument()にnargsというパラメータを渡すと可変長引数を実現できます。
複数の引数
integerの数字を指定するとその数の引数を要求するようになります。
import argparse parser = argparse.ArgumentParser() parser.add_argument('--foo', nargs=2) parser.add_argument('bar', nargs=1) args = parser.parse_args() print(args)
これはこうなります。
% python test3.py usage: test3.py [-h] [--foo FOO FOO] bar test3.py: error: too few arguments % python test3.py bar Namespace(bar=['bar'], foo=None) % python test3.py bar --foo hoge usage: test3.py [-h] [--foo FOO FOO] bar test3.py: error: argument --foo: expected 2 argument(s) % python test3.py bar --foo hoge hige Namespace(bar=['bar'], foo=['hoge', 'hige'])
オプション引数
'?'を指定するとあってもなくても良くなります。
これは例えば入出力ファイルの指定で指定がなければ標準入出力を指定する、などに使えます。
parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin) parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'), default=sys.stdout)
こうなります。
% python test3-2.py --help usage: test3-2.py [-h] [infile] [outfile] positional arguments: infile outfile % python test3-2.py Namespace(infile=<open file '<stdin>', mode 'r' at 0x100299150>, outfile=<open file '<stdout>', mode 'w' at 0x1002991e0>) % python test3-2.py hoge Namespace(infile=<open file 'hoge', mode 'r' at 0x100450b70>, outfile=<open file '<stdout>', mode 'w' at 0x1002991e0>) % python test3-2.py hoge hoge Namespace(infile=<open file 'hoge', mode 'r' at 0x100450b70>, outfile=<open file 'hoge', mode 'w' at 0x100655300>)
argparse.FileTypeの効果により、すでにopenされた状態でinfileとoutfileに格納されています。
可変長引数
'*'を指定すると可変長引数を指定できます。(例は import など省略しています)
parser.add_argument('--foo', nargs='*') parser.add_argument('--bar', nargs='*')
% python test3-3.py --help usage: test3-3.py [-h] [--foo [FOO [FOO ...]]] [--bar [BAR [BAR ...]]] optional arguments: -h, --help show this help message and exit --foo [FOO [FOO ...]] --bar [BAR [BAR ...]] % python test3-3.py --foo 1 2 3 --bar A B C Namespace(bar=['A', 'B', 'C'], foo=['1', '2', '3'])
'*'の代わりに'+'を使うと指定が一つもない場合にエラーメッセージが表示されるようになります。
例 その4 サブコマンド
ArgumentParser.add_subparsers()を使うと、サブコマンドを定義できるようになります。
# -*- coding: utf-8 -*- import argparse parser = argparse.ArgumentParser() # トップレベルのparserを作ります parser.add_argument('--foo', action='store_true', help='foo help') subparsers = parser.add_subparsers(help='sub-command help') # a というサブコマンドのparserを作ります parser_a = subparsers.add_parser('a', help='a help') parser_a.add_argument('aaa', type=int, help='aaa help') # b というサブコマンドのparserを作ります parser_b = subparsers.add_parser('b', help='b help') parser_b.add_argument('--baz', choices='XYZ', help='baz help') args = parser.parse_args() print(args)
% python test4.py --help usage: test4.py [-h] [--foo] {a,b} ... positional arguments: {a,b} sub-command help a a help b b help optional arguments: -h, --help show this help message and exit --foo foo help % python test4.py a 11 Namespace(aaa=11, foo=False) % python test4.py b --baz X Namespace(baz='X', foo=False)
全然まだまだこんなもんじゃない
説明してませんが、例4にあるように引数を数値に限定したり、指定の中から選ばせたりもできます。他にも、値を格納する場所を指定したり、それにつれてアクションを起こしたり、ファイルをいきなり開いたり(例3でありました)、相反するオプションを指定されたときに解決する方法を書けたりと、ほんとありとあらゆることができます。さらに自分で拡張をすることもできます。
もはやoptparseを使う理由はありません。argparse、そしてそれを標準で使えるpython 2.7にすぐに移行しましょう(とか言ってみる)