pythonでコマンドラインツール書く時ほぼ必須レベルの、
clickっていうコマンドラインの引数とかいい感じにしてくれるイケてるpackageがあるけど、
http://click.pocoo.org/6/
http://blog.amedama.jp/entry/2015/10/14/232045
デコレータに指定したオプション名と引数名を対応させないとならないので、
オプションが多いと冗長になってしまうのがちょっと残念で、なんとかしたい。
before
a.py
# coding: utf-8
import click
@click.command()
@click.argument('arg_a')
@click.argument('arg_b')
@click.option('--opt-c')
@click.option('--opt-d')
def cmd(arg_a, arg_b, opt_c, opt_d):
print(locals())
if __name__ == '__main__':
cmd()
bash
$ python a.py a b --opt-c c --opt-d d
{'opt_d': 'd', 'opt_c': 'c', 'arg_b': 'b', 'arg_a': 'a'}
そこで
とりあえず **kwargs
で受けるようにしてみれば、まとめて受け取れるけど、
dictだとtypoが検知しづらいつらみがあるので、もうひと工夫。
ビルトインの type
には2種類の使い方があって、
http://jfine-python-classes.readthedocs.io/en/latest/type-name-bases-dict.html
type(name, bases, dict)
で新しい型のインスタンスを作って、dict の内容で初期化できる。
after
無名structみたいな感じで使える。
元が **kwargs
なので、普通に引数で受け取った残りをdictでまとめるのもできる。
b.py
# coding: utf-8
import click
@click.command()
@click.argument('arg_a')
@click.argument('arg_b')
@click.option('--opt-c')
@click.option('--opt-d')
def cmd(**kwargs):
opts = type('hoge', (object,), kwargs)
print(dir(opts))
print(type(opts))
print(opts.__name__)
print(opts.arg_a)
print(opts.arg_b)
print(opts.opt_c)
print(opts.opt_d)
if __name__ == '__main__':
cmd()
bash
$ python b.py a b --opt-c c --opt-d d
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'arg_a', 'arg_b', 'opt_c', 'opt_d']
<class 'type'>
hoge
a
b
c
d
っていう話。