四招美化click命令行应用
python在实现命令行工具的方面有很多有优势的库,其中Click是其中的佼佼者。
今天不是Click
的教学,参考官方文档就可以很快写出一个不错的命令行应用。今天我们来做四件事提高我们命令行应用的B格:
- 长时间任务的等待效果
- 命令行帮助的文档的美化
- 错误命令猜测提示
- 日志级别的控制
快速实现一个等待效果
在很多命令行工具的交互过程中存在着长时间等待一些任务,如果没有一些友好的提示,经常会被使用者认为
卡死或者死循环等情况。而进度条
是一个非常不错的解决方案,progressbar,progressive都是不错的选择, click
也有自己的click.progressbar
。但是遇到总体进度预先不知道的任务,例如:等待某个任务完成、等待数据加载等这些不知道什么时候才能完成的任务的时候进度条就不那么好用了。这个时候最简单的一个表示方式就是循环动画播放,比如iOS中的“转菊花”。
你可以自己写一个异步的动画播放效果,这里我就不写了。我今天要用非常简单的方法来实现这一效果,我们用 到的是blindspin,一个click-spinner的fork,没什么大变化主要是动画效果不一样。
安装
pip install blindspin
import time
import click
import blindspin
def a_long_time_task():
"""模拟一个需要等待的任务"""
time.sleep(5)
@click.command()
def cli():
# 将长时间的任务放在这个with语句中就可以了
# with中执行的任务全部结束,动画效果就会结束
with blindspin.spinner():
a_long_time_task()
if __name__ == "__main__":
cli()
效果:
美化帮助文档
click
能够非常方便的生成帮助文档,通过命令行参数--help
就能查看到。默认的帮助文档是一色的,现在我们来给它上色吧。
安装
pip install click-help-colors
这里我就用官网的例子,稍稍改一点点,自己体会一下就会用了。
import click
from click_help_colors import HelpColorsGroup, HelpColorsCommand
@click.group(
cls=HelpColorsGroup,
help_headers_color='yellow',
help_options_color='magenta')
def cli():
"""主命令"""
pass
@cli.command()
@click.option('--count', default=1, help='Some number.')
def command1(count):
click.echo('command 1')
@cli.command(cls=HelpColorsCommand, help_options_color='blue')
@click.option('--name', help='Some string.')
def command2(name):
click.echo('command 2')
if __name__ == "__main__":
cli()
效果
python colour_help.py --help
python colour_help.py command1 --help
python colour_help.py command2 --help
猜测用户希望的命令
当我们子命令比较多的时候,用户可能会记错、拼错或者打错。能提示用户正确的命令那是多么cool的一件事, 然而我们经常用的git就有这样的功能。
这里我输错
push
命令,git提示我们正确的写法。这个功能已经有人帮我们实现了,就是click-didyoumean
安装
pip install click-didyoumean
用法
为你的命令组指定
DYMGroup
类import click from click_didyoumean import DYMGroup @click.group(cls=DYMGroup) def cli(): pass @cli.command() def foo(): pass @cli.command() def bar(): pass @cli.command() def barrr(): pass if __name__ == "__main__": cli()
将需要的子命令放入
DYMCommandCollection
中import click from click_didyoumean import DYMCommandCollection @click.group() def cli1(): pass @cli1.command() def foo(): pass @cli1.command() def bar(): pass @click.group() def cli2(): pass @cli2.command() def barrr(): pass cli = DYMCommandCollection(sources=[cli1, cli2]) if __name__ == "__main__": cli()
DYMGroup
和DYMCommandCollection
类有两个配置项,
参数 | 类型 | 默认值 | 描述 |
max_suggestions | int | 3 | 最大建议条目数 |
cutoff | float | 0.5 | 小于这个可能性分数的将会被忽略 |
例:
@cli.group(cls=DYMGroup, max_suggestions=2, cutoff=0.7)
def cli():
pass
... or ...
cli = DYMCommandCollection(sources=[cli1, cli2], max_suggestions=2, cutoff=0.7)
这里有个小插曲,如果你想同时使用click-help-colors
和click-didyoumean
,那么你会发现他们都需要对cls
参数进行修改。怎么同时让两者都生效呢?这里可以使用python的多重继承功能。
class CLI(DYMGroup, click_help_colors.HelpColorsGroup):
pass
@click.group(
cls=CLI, help_headers_color='yellow', help_options_color='blue')
def cli():
pass
这样我们就能使得我们的命令行应用同时具备着两种功能了👍。
用户指定日志等级
我们经常有这样的情况,希望日志等级可以通过参数的传入来控制。比如,默认情况只输出一下必要信息。加入参数-v
可以显示更多详细信息。
通常情况我们可以这样实现:
import logging
logger = logging.getLogger(__name__)
@click.command()
@click.option('--verbose', '-v', default=False, is_flag=True)
def cli(verbose):
if verbose:
logger.setLevel(logging.ERROR)
else:
logger.setLevel(logging.INFO)
logger.info("普通输出信息")
logger.error("详细信息")
然而click-log已经为我们实现了这一功能,使用python最大的好处就是DRY(Don't repeat yourself)
安装
pip install click-log
这里我们仅仅演示基本的做法,更多自定义的内容请参考官方文档
import logging
import click_log
logger = logging.getLogger(__name__)
click_log.basic_config(logger)
@click.command()
@click_log.simple_verbosity_option(logger)
def cli():
logger.info("Dividing by zero.")
try:
1 / 0
except:
logger.error("Failed to divide by zero.")
以上代码,中click_log.simple_verbosity_option
装饰器为命令增加了一个--verbosity
可选参数,
它接受DEBUG
,INFO
,WARNING
,ERROR
或者CRITICAL
这几个值来控制日志级别。
好了以上就是我们用来美化click
命令行应用的四招。