PythondでCLIを作成するときの備忘録です。
環境は以下の通りです。
環境
- Python 3.7
argparseモジュール
通常
コマンドライン引数のグループ化
add_argument_group
で、コマンドライン引数をグループ化できます。
共通のオプションなどは、グループ化するとヘルプ表示が見やすくなります。
group = parser.add_argument_group("global optional arguments")
group.add_argument('--yes', action="store_true", help="処理中に現れる問い合わせに対して、常に'yes'と回答します。")
group.add_argument('--logdir', type=str, default=".log", help="ログファイルを保存するディレクトリを指定します。")
$ python test_command.py -h
optional arguments:
-h, --help show this help message and exit
global optional arguments:
--yes 処理中に現れる問い合わせに対して、常に'yes'と回答します。
--logdir LOGDIR ログファイルを保存するディレクトリを指定します。
相互排他
オプション--foo
と--bar
を同時に指定することを禁止する場合、add_mutually_exclusive_group
メソッドを使います。
https://docs.python.org/ja/3/library/argparse.html#mutual-exclusion
共通のオプション引数
各コマンドで共通の引数を指定したい場合、ArgumentParser
のparents
引数を利用します。
https://docs.python.org/ja/3/library/argparse.html#parents
version情報の表示
action="version"
を指定します。
import argparse
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('--version', action='version', version='%(prog)s 2.0')
parser.parse_args(['--version'])
https://docs.python.org/ja/3/library/argparse.html#action 引用
デフォルトで、長いオプションは先頭の一文字に短縮可能
parse_args() メソッドは、デフォルトで、長いオプションに曖昧さがない (先頭の文字が一意である) かぎり、先頭の一文字に短縮して指定できます
allow_abbrev
をFalse
をすることで、この機能は無効化されます。
サブコマンド関係
1階層のサブコマンド
gitコマンドのように、my_git push
、my_git pull
のようなサブコマンドを作成します。
サブコマンドに対応する関数は、set_defaults()
で紐づけられます。
import argparse
def push(args):
print("Execute push command")
print(args)
def pull(args):
print("Execute pull command")
print(args)
def main():
parser = argparse.ArgumentParser(prog='PROG')
subparsers = parser.add_subparsers(help='sub-command help')
# pull コマンドのパーサを作成
parser_push = subparsers.add_parser('push', help='push help')
parser_push.add_argument('--bar', type=str, help='bar help')
parser_push.set_defaults(subcommand_func=push)
# push コマンドのパーサを作成
parser_pull = subparsers.add_parser('pull', help='pull help')
parser_pull.add_argument('--foo', type=str, help='foo help')
parser_pull.set_defaults(subcommand_func=pull)
args = parser.parse_args()
if hasattr(args, 'subcommand_func'):
# set_defaultsで割り当てた関数を実行する
args.subcommand_func(args)
else:
# pull or pushが指定されない場合
parser.print_help()
if __name__ == "__main__":
main()
$ python my_git.py push --bar hoge
Execute push command
Namespace(bar='hoge', subcommand_func=<function push at 0x0000027268F4C268>)
$ python my_git.py pull --foo hoge
Execute pull command
Namespace(foo='hoge', subcommand_func=<function pull at 0x000002134792CD90>)
$ python my_git.py
usage: my_git.py [-h] {push,pull} ...
positional arguments:
{push,pull} sub-command help
push push help
pull pull help
optional arguments:
-h, --help show this help message and exit
2階層のサブコマンド
AWS CLIのように、my_aws ec2 wait
、my_aws sns publish
のようなサブコマンドを作成します。
1つ目のサブコマンド、2つ目のサブコマンドが指定されない場合は、ヘルプを表示するようにしました。
import argparse
def wait(args):
print("Execute ec2 wait command")
print(args)
def publish(args):
print("Execute sns publish command")
print(args)
def main():
parser = argparse.ArgumentParser()
parser.set_defaults(command_help=parser.print_help)
subparsers = parser.add_subparsers(help='sub-command help')
# ec2 コマンドのパーサを作成
parser_ec2 = subparsers.add_parser('ec2', help='ec2 help')
parser_ec2.set_defaults(command_help=parser_ec2.print_help)
subparser_ec2 = parser_ec2.add_subparsers()
# ec2 wait コマンドのパーサ作成
parser_ec2_wait = subparser_ec2.add_parser('wait', help='ec2 wait help')
parser_ec2_wait.set_defaults(subcommand_func=wait)
# sns コマンドのパーサを作成
parser_sns = subparsers.add_parser('sns', help='sns help')
parser_ec2.set_defaults(command_help=parser_ec2.print_help)
subparser_sns = parser_sns.add_subparsers()
# sns publish コマンドのパーサ作成
parser_sns_publish = subparser_sns.add_parser('publish', help='sns publish help')
parser_sns_publish.set_defaults(subcommand_func=publish)
args = parser.parse_args()
if hasattr(args, 'subcommand_func'):
args.subcommand_func(args)
else:
# pull or pushが指定されない場合
args.command_help()
if __name__ == "__main__":
main()
$ python my_aws.py
usage: my_aws.py [-h] {ec2,sns} ...
positional arguments:
{ec2,sns} sub-command help
ec2 ec2 help
sns sns help
optional arguments:
-h, --help show this help message and exit
$ python my_aws.py ec2
usage: my_aws.py ec2 [-h] {wait} ...
positional arguments:
{wait}
wait ec2 wait help
optional arguments:
-h, --help show this help message and exit
$ python my_aws.py sns publish
Execute sns publish command
Namespace(command_help=<bound method ArgumentParser.print_help of ArgumentParser(prog='my_aws.py', usage=None, description=None, formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True)>, subcommand_func=<function publish at 0x00000286B96BCD90>)