Python

Pythonのargparseでサブコマンドを実現する

More than 1 year has passed since last update.

Python 3 で argparse を使ってサブコマンドをパースする方法を説明します。が、Python に詳しくないのでもっといい方法があるかもしれません。標準ライブラリだけで済ませたいけど、argparse は高機能過ぎて使いづらい…


やりたいこと



  • git コマンドのように git addgit commit を作る

  • サブコマンドごとのヘルプを見る git help を作る


サンプルコード

ポイントとしては次の通りです。



  • parser.add_subparsers()parser を入れ子にする


  • parser_〇〇.set_defaults(handler=関数名) でサブコマンドごとの処理をハンドラ関数に移譲する

  • 未知のサブコマンドが指定された場合はヘルプを表示する


git.py

#!/usr/bin/env python

# coding: utf-8

import argparse

# サブコマンドの実際の処理を記述するコールバック関数

def command_add(args):
print(args)

def command_commit(args):
print(args)

def command_help(args):
print(parser.parse_args([args.command, '--help']))

# コマンドラインパーサーを作成
parser = argparse.ArgumentParser(description='Fake git command')
subparsers = parser.add_subparsers()

# add コマンドの parser を作成
parser_add = subparsers.add_parser('add', help='see `add -h`')
parser_add.add_argument('-A', '--all', action='store_true', help='all files')
parser_add.set_defaults(handler=command_add)

# commit コマンドの parser を作成
parser_commit = subparsers.add_parser('commit', help='see `commit -h`')
parser_commit.add_argument('-m', metavar='msg', help='commit message')
parser_commit.set_defaults(handler=command_commit)

# help コマンドの parser を作成
parser_help = subparsers.add_parser('help', help='see `help -h`')
parser_help.add_argument('command', help='command name which help is shown')
parser_help.set_defaults(handler=command_help)

# コマンドライン引数をパースして対応するハンドラ関数を実行
args = parser.parse_args()
if hasattr(args, 'handler'):
args.handler(args)
else:
# 未知のサブコマンドの場合はヘルプを表示
parser.print_help()



実行例

サブコマンドを指定しないと、トップレベルのヘルプメッセージが表示されます。

$ python git.py

usage: git.py [-h] {commit,add,help} ...

Fake git command

positional arguments:
{commit,add,help}
commit see `commit -h`
add see `add -h`
help see `help -h`

optional arguments:
-h, --help show this help message and exit

サブコマンドに -h オプションを付けると、サブコマンドレベルのヘルプメッセージが表示されます。これは、argparse がよしなにやってくれるからです。

$ python git.py commit -h

usage: git.py commit [-h] [-m msg]

optional arguments:
-h, --help show this help message and exit
-m msg commit message

help サブコマンドを使った場合も同様です。こちらは自前で実装したからです。

$ python git.py help commit

usage: git.py commit [-h] [-m msg]

optional arguments:
-h, --help show this help message and exit
-m msg commit message

最後に、 addcommit サブコマンドも期待通りに動作します。

$ python git.py add

Namespace(all=False, handler=<function command_add at 0x102973c80>)

$ python git.py commit -m "message"
Namespace(handler=<function command_commit at 0x10510e7b8>, m='message')


参考情報