Python Cli 编写指南

python实现cli

环境:

  • python 3.8

  • python自带argparse

指南

简单示例 : cli.py

import argparse


def cli():
    parser = argparse.ArgumentParser(description='CLI描述')
    subparsers = parser.add_subparsers(metavar='子命令')

    # 添加子命令,演示没有参数
    one_parser = subparsers.add_parser('one', help='第一个命令')
    one_parser.set_defaults(handle=handle_one)

    # 解析命令
    args = parser.parse_args()
    # 1.第一个命令会解析成handle,使用args.handle()就能够调用
    if hasattr(args, 'handle'):
        args.handle(args)
    # 2.如果没有handle属性,则表示未输入子命令,则打印帮助信息
    else:
        parser.print_help()


def handle_one(args):
    print('handle_one')


if __name__ == '__main__':
    cli()

调用:

$ python cli.py
usage: cli_1.py [-h] 子命令 ...

CLI描述

positional arguments:
  子命令
    one       第一个命令

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

$ python cli.py one
handle_one

增加第二个命令

import argparse


def cli():
    parser = argparse.ArgumentParser(description='CLI描述')
    subparsers = parser.add_subparsers(metavar='子命令')

    # 添加子命令,演示没有参数
    one_parser = subparsers.add_parser('one', help='第一个命令')
    one_parser.set_defaults(handle=handle_one)

    # 添加子命令,演示有参数
    two_parser = subparsers.add_parser('two', help='第二个命令')
    # 参数(简写,全称,类型,是否必填,帮助说明)
    two_parser.add_argument('-s', '--str', type=str, required=True,
                            help='一个字符串类型参数')
    # 参数(简写,全称,类型,默认值,帮助说明)
    two_parser.add_argument('-d', '--default', type=str, default='默认值',
                            help='这个命令有默认值')
    # 参数(简写,全称,类型,帮助说明)
    two_parser.add_argument('-ts', '--the-str', type=str,
                            help='当全称有横线时,属性名转换为下划线,即 the_str')
    two_parser.set_defaults(handle=handle_two)

    # 解析命令
    args = parser.parse_args()
    # 1.第一个命令会解析成handle,使用args.handle()就能够调用
    if hasattr(args, 'handle'):
        # 1.1.其他参数会被解析成args的属性,以命令全称为属性名
        args.handle(args)
    # 2.如果没有handle属性,则表示未输入子命令
    else:
        parser.print_help()


def handle_one(args):
    # 无参数
    print('handle_one')


def handle_two(args):
    print('handle_two')
    print(f'str:{args.str}')
    print(f'default:{args.default}')
    print(f'the-str:{args.the_str}')


if __name__ == '__main__':
    cli()
  • 调用:

    $ python cli.py
    usage: cli.py [-h] 子命令 ...
    
    CLI描述
    
    positional arguments:
    子命令
      one       第一个命令
      two       第二个命令
    
    optional arguments:
    -h, --help  show this help message and exit
  • 调用one不受影响

    $ python cli.py one
    handle_one
  • 调用two会显示需要必填项-s

    $ python cli.py two
    usage: cli.py two [-h] -s STR [-d DEFAULT] [-ts THE_STR]
    cli.py two: error: the following arguments are required: -s/--str
  • 输入-h查看帮助

    $ python cli.py two -h
    usage: cli.py two [-h] -s STR [-d DEFAULT] [-ts THE_STR]
    
    optional arguments:
    -h, --help            show this help message and exit
    -s STR, --str STR     一个字符串类型参数
    -d DEFAULT, --default DEFAULT
                          这个命令有默认值
    -ts THE_STR, --the-str THE_STR
                          当全称有横线时,属性名转换为下划线,即 the_str
  • 输入-s参数(或全称--str)

    • 可以看到加了默认值的会显示默认值
    • 没默认值且非必填项值为None
    $ python cli.py two -s 哈哈
    handle_two
    str:哈哈
    default:默认值
    the-str:None
  • 输入有默认值的参数-d (或全称--default)

    • 输入的值会覆盖默认值
    $ python cli.py two -s 哈哈 --default 改了
    handle_two
    str:哈哈
    default:改了
    the-str:None
  • 输入所有参数

    $ python cli.py two -s 哈哈 --default 改了 -ts 赋值了
    handle_two
    str:哈哈
    default:改了
    the-str:赋值了

其他代码使用

在"setup.py"文件中

import setuptools

setuptools.setup(
  # 省略其他参数
  entry_points={
    'console_scripts': [
        'my-cli = my.cli:cli'
    ]
  }
)
  • 'my-cli = my.cli:cli'就是替换内容

    • 'my-cli'

      • 上传pypi后,拉取这个库,就能够使用'my-cli'来调用cli
      • 如'my-cli one' / 'my-cli two -h'
    • 'my.cli:cli'

      • '完整类名:方法名'
      • 目录结构如下方结构
      • cli命令需要放在模块下
      • 不能放在根目录下,否则会报错找不到模块

文件目录结构:

root

  • my

    • \_\_init\_\_.py
    • cli.py

参考资料:

https://zhuanlan.zhihu.com/p/...

言午日尧耳总
1 声望6 粉丝

不秃顶、不猝死,顺顺利利活到100可以吗?