google-apputilsって何者?
Operations Research関連のオープンソースソフトウェアを探していたら,2010年9月から始まってgooglerが中心となって開発しているようなor-toolsというプロジェクトを見つけました.or-toolsはswigを使ったPythonのライブラリになっていてサンプルコードも多数含まれているのですが,サンプルコード一部(例えばknapsack.py)の中に下のような見慣れないコードがありました.
from google.apputils import app # 省略 def main(unused_argv): # 省略 if __name__ == '__main__': app.run()
google-apputils-pythonとはGoogle内製のアプリでも使用されてる便利ツールのようです.残念ながらまだドキュメントが充実していないようなのですが,どんなことができるのか簡単に見ていきましょう.まずは次のようなシンプルなPythonファイルを用意します.
#!/usr/bin/env python '''How to use this module''' from google.apputils import app def main(argv): if len(argv) < 2: raise app.UsageError('usage error') print argv if __name__ == '__main__': app.run()
sample.pyとして実行します.
$ sample.py --help How to use this module flags: google.apputils.app: -?,--[no]help: show this help --[no]helpshort: show usage only for this module --[no]helpxml: like --help, but generates XML output --[no]run_with_pdb: Set to true for PDB debug mode (default: 'false') --[no]run_with_profiling: Set to true for profiling the script. Execution will be slower, and the output format might change over time. (default: 'false') --[no]show_build_data: show build data and exit gflags: --flagfile: Insert flag definitions from the given file into the command line. (default: '') --undefok: comma-separated list of flag names that it is okay to specify on the command line even if the program does not define a flag with that name. IMPORTANT: flags in this list that have arguments MUST use the --flag=value format. (default: '') $ sample.py --helpshort How to use this module $ sample.py How to use this module usage error $ sample.py arg ['./sample.py', 'arg'] $ sample.py --run_with_profiling arg ['./sample.py', 'arg'] 4 function calls in 0.002 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 0.000 0.000 :0(len) 1 0.002 0.002 0.002 0.002 :0(setprofile) 1 0.000 0.000 0.002 0.002 profile:0(<function main at 0x1010679b0>) 0 0.000 0.000 profile:0(profiler) 1 0.000 0.000 0.000 0.000 sample.py:6(main) $ sample.py --run_with_pdb arg > /Users/likr/python/test/sample.py(7)main() -> if len(argv) < 2: (Pdb)
このようにapputilsを使えば,モジュールのdocstringをusageとして表示させたり,コマンドライン引数を渡すだけでプロファイラやデバッガの起動ができるようになります.apputilsでハンドルされるフラグはmainには渡ってきません.また,以下のようにフラグを自分で追加することもできます.
#!/usr/bin/env python '''How to use this module''' from google.apputils import app import gflags class MyFlag(gflags.BooleanFlag): def __init__(self): gflags.BooleanFlag.__init__(self, 'myflag', 0, 'my flag', short_name='m', allow_override=1) def Parse(self, arg): if arg: print 'myflag is used' def main(argv): if len(argv) < 2: raise app.UsageError('usage error') print argv if __name__ == '__main__': gflags.DEFINE_flag(MyFlag()) app.run()
$ sample.py -? How to use this module flags: ./sample.py: -m,--[no]myflag: my flag google.apputils.app: -?,--[no]help: show this help --[no]helpshort: show usage only for this module --[no]helpxml: like --help, but generates XML output --[no]run_with_pdb: Set to true for PDB debug mode (default: 'false') --[no]run_with_profiling: Set to true for profiling the script. Execution will be slower, and the output format might change over time. (default: 'false') --[no]show_build_data: show build data and exit gflags: --flagfile: Insert flag definitions from the given file into the command line. (default: '') --undefok: comma-separated list of flag names that it is okay to specify on the command line even if the program does not define a flag with that name. IMPORTANT: flags in this list that have arguments MUST use the --flag=value format. (default: '') $ sample.py --myflag aaa myflag is used ['./sample.py', 'aaa'] $ sample.py -m aaa myflag is used ['./sample.py', 'aaa']
gflags.BooleanFlag.__init__の第2引数が--xxxのxxxに,shortname引数が-yのyに対応します.
普通のmainの書き方と大きく変わらない書き方で,コマンドライン引数によるプロファイラの起動ができるのは便利そうだと思いました.google-apputilsはPyPIにも登録されているのでeasy_installやpipでもインストールできます.google-apputilsには,今回紹介した以外にもアプリケーションのサブコマンド,デバッグ,プロファイリング,日付などを便利に扱う機能があるようです.他の機能の紹介は機会があれば後日.