Pythonでコマンドライン引数を解析する

2016年3月23日水曜日

python

t f B! P L
python hoge.py fuga --foo bar こんなのを処理したい。 argparseやdocoptやclickというものがあるらしいので軽く調べた。
  • 特に制限がなければdocoptかclick
  • 標準ライブラリを使いたい場合はargparse
  • 大したことしないのでとりあえずsys.argv
これを上から考えていけば良さそう。



題材

hoge.pyというファイル名で作るとして、
python hoge.py parrot
> This is a parrot
と返ってくる。
-c, --capをつけるとThis is a PARROTになり、
-a, --adj lateでThis is a late parrotとなり、
-d, --deadをつけるとThis is a ex-parrotとなる。
ifの分岐が雑とか冠詞が雑とかは気にしない。

sys.argv

省略。

argparse

標準ライブラリなのでpip installせずに使える。
def func(args):
    name = args.name
    if args.cap:
        name = name.upper()
    if args.adj:
        name = args.adj + ' ' + name
    if args.dead:
        name = 'ex-' + name
    print('This is a ' + name)


if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(description='test')
    parser.add_argument('name', type=str)
    parser.add_argument('-c', '--cap', dest='cap', action='store_true')
    parser.add_argument('-d', '--dead', dest='dead', action='store_true',
                        help='add "ex-"')
    parser.add_argument('-a', '--adj', dest='adj', action='store')
    args = parser.parse_args()
    func(args)
実行するとこんな感じ。helpも自動で処理されて便利。
docoptとclickも似たような結果になる。
(_venv) E:\projects\clparsetest>python try_argparse.py --help
usage: try_argparse.py [-h] [-c] [-d] [-a ADJ] name

test

positional arguments:
  name

optional arguments:
  -h, --help         show this help message and exit
  -c, --cap
  -d, --dead         add "ex-"
  -a ADJ, --adj ADJ

(_venv) E:\projects\clparsetest>python try_argparse.py parrot
This is a parrot

(_venv) E:\projects\clparsetest>python try_argparse.py parrot --adj late
This is a late parrot

(_venv) E:\projects\clparsetest>python try_argparse.py parrot -d
This is a ex-parrot

(_venv) E:\projects\clparsetest>python try_argparse.py parrot -dc
This is a ex-PARROT

docopt

先にhelpを書いてそれを解析するかっこいい発想。
"""test

Usage:
    prog.py [-h] [--cap] [-d] [--adj=<adj>] <name>

options:
    -h, --help  show this help message
    -c, --cap   capitalize name
    -d, --dead  add ex-
    -a, --adj=<adj>
"""


def func(args):
    name = args['<name>']
    if args['--cap']:
        name = name.upper()
    if args['--adj']:
        name = args['--adj'] + ' ' + name
    if args['--dead']:
        name = 'ex-' + name
    print('This is a ' + name)


if __name__ == '__main__':
    import docopt
    args = docopt.docopt(__doc__)
    func(args)

click

デコレータを使ったPythonらしい作り。
import click


@click.command()
@click.option('-a', '--adj', default=None)
@click.option('-d', '--dead', is_flag=True, help='add "ex-"')
@click.option('-c', '--cap', is_flag=True)
@click.argument('name')
def func(name, cap, dead, adj):
    name = name
    if cap:
        name = name.upper()
    if adj:
        name = adj + ' ' + name
    if dead:
        name = 'ex-' + name
    click.echo('This is a ' + name)

if __name__ == '__main__':
    func()

QooQ