vlambda博客
学习文章列表

创建漂亮的Flask命令行界面

10287

创建漂亮的Flask命令行界面

click

Click 可以帮助写出跟漂亮的命令行接口.官网https://click.palletsprojects.com/en/7.x/

比如官网的实例:(更多参数请查询官方API)

# hello.py
import click

@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',help='The person to greet.')
def hello(count, name):
 """Simple program that greets NAME for a total of COUNT times."""
  for x in range(count):
      click.echo('Hello %s!' % name)

if __name__ == '__main__':
  hello()

运行结果

$ python hello.py --count=3
Your name: John
Hello John!
Hello John!
Hello John!

它能自动生成帮助信息

$ python hello.py --help
Usage: hello.py [OPTIONS]

Simple program that greets NAME for a total of COUNT times.

Options:
--count INTEGER  Number of greetings.
--name TEXT      The person to greet.
--help           Show this message and exit.

如果没有安装,需要使用pip安装

$ pip install click

使用click.command() 装饰器

Click 中最基础的就是单个命令(command),通过装饰器@click.command() 可以将一个 Python 方法转换为一个 Click 命令。最简单的情况下如下所示:

#  click_manager.py
import click

@click.command()
def hello():
  click.echo('Hello World!')
 
if __name__ == '__main__':
 hello()

在终端运行,类型这样

$ python click_manager.py
Hello World

这里为什么要使用click.echo()而不是print()?官网的解释是为了同时支持python2python3 ,如果不需要它,可以使用print() 函数

使用click.option() 装饰器

Click 中的 option 是命令中的参数获取方式,可以通过不同的形式获取输入参数

最基础的情况下可以使用 option 表示一个基础的输入参数:

@click.command()
@click.option('--email',default=None)
def add_email(email):
  click.echo('email:{}'.format(email))

if __name__ == '__main__':
  add_email()   # 注意,这里执行的是单个命令

这里执行的都是单个命令,所以最后指定了add_email()

执行

$ python click_manager.py  [email protected]
email:[email protected]

除了最基本的用法,还有一个可选择的参数

  • 使用 nargs可以支持多个同样类型的参数
@click.command()
@click.option('--pos', nargs=2, type=float)
def findme(pos):
    click.echo('%s / %s' % pos)
    
"""
命令行
$ findme --pos 2.0 3.0
2.0/3.0
"""
    
  • 使用类型元组支持多个不同类型的参数
@click.command()
@click.option('--item', type=(str, int))
def putitem(item):
    click.echo('name=%s id=%d' % item)
    
"""
$ putitem --item peter 1338
name=peter id=1338
"""
    
  • 使用 / 分开参数表示布尔值
import sys

@click.command()
@click.option('--shout/--no-shout', default=False)
def info(shout):
    rv = sys.platform
    if shout:
        rv = rv.upper() + '!!!!111'
    click.echo(rv)

"""
$ info --shout
LINUX!!!!111
$ info --no-shout
linux
"""
    
  • 使用 clickchoice() 用于指定参数从特定列表中选择
@click.option('--hash-type', type=click.Choice(['md5', 'sha1']))
  • 使用 prompt 实现交互式的输入
@click.option('--name', prompt='Your name please')
  • 使用 hide_input 可以实现隐藏输入,使用 confirmation_prompt,实现两次输入并对比,适合密码输入的情况
@click.option('--password', prompt=True, hide_input=True,  confirmation_prompt=True)
  • 使用 envvar 可以获取环境变量中的值
@click.option('--username', envvar='USERNAME')
  • 使用 IntRange 获取特定范围类的值
@click.option('--digit', type=click.IntRange(0, 10))

使用click.argument() 装饰器

argumentoption 类似,但是argument 指定的是位置参数.它支持option 的部分功能.

最基础的情况下,使用和option 类似.一般需要自动特定参数对应的类型,如果不指定,会使string 类型.

@click.command()
@click.argument('filename')
def touch(filename):
  click.echo(filename)

高级用法:

  • 支持可变参数,利用 nargs可以支持可变的参数, nargs=-1 表示不限数量的参数.
@click.command()
@click.argument('src', nargs=-1)
@click.argument('dst', nargs=1)
def copy(src, dst):
    for fn in src:
        click.echo('move %s to folder %s' % (fn, dst))
  • 支持文件类型
@click.argument('input', type=click.File('rb'))
  • 支持文件路径类型
@click.argument('f', type=click.Path(exists=True))

命令组嵌套命令

可以将命令分组进行管理,在使用中可以使用@click.group() 装饰器指定组,此后可以使用组名构建子命令。同时可以设定组内命令的回调,组内的任意子命令执行时,都可以触发回调。使用如下所示:

@click.group()
@click.option('--debug/--no-debug', default=False)
def cli(debug):
   click.echo('Debug mode is %s' % ('on' if debug else 'off'))

@cli.command()
def sync():
   click.echo('Synching')

在上面的代码中可以看到,使用@click.group() 装饰器装饰了cli() 方法,cli 可以理解为组名,后续即可使用@cli.command() 代替@click.command() 装饰sync() 方法,sync() 方法就是组内的子命令,而cli()方法即为子命令执行后出发的回调。可以看到执行子命令sync() 方法后的现场如下所示:

$ tool.py --debug sync
Debug mode is on
Synching

可以看到上面的执行情况,子命令sync 执行时,不仅执行了sync() 方法中的代码,还执行了回调方法cli() 方法中的代码。

在使用命令组时,还可以在命令组和子命令之间进行参数的传递,此时可以使用@click.pass_context 装饰器进行,具体的细节可以查看官方文档 。

任意执行命令

Click 与 Flask-script 的使用极其类似,而且更灵活,更强大。但是直接使用@click.command() 看起来似乎是每次执行确定的单个命令,有没有办法实现类似 Flask-script 一样任意选择的命令呢 ?

答案是可以的,但是必须借助于命令组,建立一个命令组,执行的命令都是命令组的子命令,执行时就可以通过参数指定执行的命令了,因此最终替代的 Flask-script 的 Click 代码如下所示:

# manage.py 
@click.group()
def cli():
   pass

@cli.command()
def hello():
   click.echo('hello')

if __name__ == '__main__':
   cli()

对于上面的代码,可以直接执行python manage.py hello 从而执行hello() 方法中的代码

创建漂亮的Flask命令行界面
wechat
- END -
Flask学习笔记 发起了一个读者讨论 留言板(留言不支持实时刷新,有1-2分钟延迟) 精选讨论内容
NYK

hello everyone


点击左下角查看更多