大家都说好用的Python命令行库click的使用


Posted in Python onNovember 07, 2019

一、前言

在本系列前面几篇文章中,我们分别介绍了 argparse 和 docopt 的主要功能和用法。它们各具特色,都能出色地完成命令行任务。argparse 是面向过程的,需要先设置解析器,再定义参数,再解析命令行,最后实现业务逻辑。而 docopt 先用声明式的语法定义出参数,再过程式地解析命令行和实现业务逻辑。在一些人看来,这些方式都不够优雅。

而今天要介绍的 click[2] 则是用一种你很熟知的方式来玩转命令行。命令行程序本质上是定义参数和处理参数,而处理参数的逻辑一定是与所定义的参数有关联的。那可不可以用函数和装饰器来实现处理参数逻辑与定义参数的关联呢?而 click 正好就是以这种方式来使用的。

本系列文章默认使用 Python 3 作为解释器进行讲解。若你仍在使用 Python 2,请注意两者之间语法和库的使用差异哦~

二、介绍click

是一个以尽可能少的代码、以组合的方式创建优美的命令行程序的 Python 包。它有很高的可配置性,同时也能开箱即用。

它旨在让编写命令行工具的过程既快速又有趣,还能防止由于无法实现预期的 CLI API 所产生挫败感。它有如下三个特点:

  • 任意嵌套命令
  • 自动生成帮助
  • 支持运行时延迟加载子命令

三、快速开始

3.1 业务逻辑

首先定义业务逻辑,是不是感觉到有些难以置信呢?

不论是 argparse 还是 docopt,业务逻辑都是被放在最后一步,但 click 却是放在第一步。细想想 click 的这种方式才更符合人的思维吧?不论用什么命令行框架,我们最终关心的就是实现业务逻辑,其它的能省则省。

我们以官方示例为例,来介绍 click 的用法和哲学。假设命令行程序的输入是 name 和 count,功能是打印指定次数的名字。

那么在 hello.py 中,很容易写出如下代码:

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)

这段代码的逻辑很简单,就是循环 count 次,使用 click.echo 打印 name。其中,click.echo 和 print 的作用相似,但功能更加强大,能处理好 Unicode 和 二进制数据的情况。

3.2 定义参数

很显然,我们需要针对 count 和 name 来定义它们所对应的参数信息。

  • count 对应为命令行选项 --count,类型为数字,我们希望在不提供参数时,其默认值是 1
  • name 对应为命令行选项 --name,类型为字符串,我们希望在不提供参数时,能给人提示

使用 click,就可以写成下面这样:

from click 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): 
  ...

在上面的示例中:

  1. 使用装饰器的方式,即定义了参数,又将之与处理逻辑绑定,这真是优雅。和 argparse、docopt 比起来,就少了一步绑定过程
  2. 使用 click.command 表示 hello 是对命令的处理
  3. 使用 click.option 来定义参数选项
    1. 对于 --count 来说,使用 default 来指定默认值。而由于默认值是数字,进而暗示 --count 选项的类型为数字
    2. 对于 --name 来说,使用 prompt 来指定未输入该选项时的提示语
    3. 使用 help 来指定帮助信息

不论是装饰器的方式、还是各种默认行为,click 都是像它的介绍所说的那样,让人尽可能少地编写代码,让整个过程变得快速而有趣。

3.3 代码梳理

使用 click 的方式非常简单,我们将上文的代码汇总下,以有一个更清晰的认识:

# 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()

若我们指定次数和名字:

$ python3 hello.py --count 2 --name Eric 
Hello Eric! 
Hello Eric!

若我们什么都不指定,则会提示输入名字,并默认输出一次:

$ python3 hello.py 
Your name: Eric 
Hello Eric!

我们还可以通过 --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.

四、小结

click 的思路非常简单,定义处理函数,通过它的装饰器来定义参数。使用装饰器的绝妙之处就在于把定义和绑定这两个步骤合为一个步骤,使得整个过程变得如丝般顺滑。

click 除了以 Pythonic 的方式让命令行程序的实现变得更加优雅和好用外,还提供了比 argparse 和 docopt 都要强大的功能。在接下来几节中,我们将会逐步揭开它的面纱。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python获取网页上图片下载地址的方法
Mar 11 Python
Python查找函数f(x)=0根的解决方法
May 07 Python
Python实现信用卡系统(支持购物、转账、存取钱)
Jun 24 Python
python: line=f.readlines()消除line中\n的方法
Mar 19 Python
python求最大连续子数组的和
Jul 07 Python
详解Python 爬取13个旅游城市,告诉你五一大家最爱去哪玩?
May 07 Python
Django模板Templates使用方法详解
Jul 19 Python
python图形用户接口实例详解
Dec 16 Python
python用pip install时安装失败的一系列问题及解决方法
Feb 24 Python
Python web如何在IIS发布应用过程解析
May 27 Python
用60行代码实现Python自动抢微信红包
Feb 04 Python
用Python将GIF动图分解成多张静态图片
Jun 11 Python
flask 实现token机制的示例代码
Nov 07 #Python
python3反转字符串的3种方法(小结)
Nov 07 #Python
Python中__repr__和__str__区别详解
Nov 07 #Python
Python通过Manager方式实现多个无关联进程共享数据的实现
Nov 07 #Python
Python上下文管理器类和上下文管理器装饰器contextmanager用法实例分析
Nov 07 #Python
Python中xml和dict格式转换的示例代码
Nov 07 #Python
python对象转字典的两种实现方式示例
Nov 07 #Python
You might like
PHP语法速查表
2006/12/06 PHP
php中将时间差转换为字符串提示的实现代码
2011/08/08 PHP
php导出word文档与excel电子表格的简单示例代码
2014/03/08 PHP
PHP cURL初始化和执行方法入门级代码
2015/05/28 PHP
PHP实现基本留言板功能原理与步骤详解
2020/03/26 PHP
javascript中怎么做对象的类型判断
2013/11/11 Javascript
Flexigrid在IE下不显示数据的有效处理方法
2014/09/04 Javascript
jQuery处理json数据返回数组和输出的方法
2015/03/11 Javascript
JS去除iframe滚动条的方法
2015/04/01 Javascript
jQuery中next方法用法实例
2015/04/24 Javascript
Bootstrap学习系列之使用 Bootstrap Typeahead 组件实现百度下拉效果
2016/07/07 Javascript
js生成随机颜色方法代码分享(三种)
2016/12/29 Javascript
javascript 注释代码的几种方法总结
2017/01/04 Javascript
JS获取本周周一,周末及获取任意时间的周一周末功能示例
2017/02/09 Javascript
关于ES6箭头函数中的this问题
2018/02/27 Javascript
浅谈高大上的微信小程序中渲染html内容—技术分享
2018/10/25 Javascript
JS原生瀑布流效果实现
2019/04/26 Javascript
vue 父组件通过v-model接收子组件的值的代码
2019/10/27 Javascript
JS如何实现网站中PC端和手机端自动识别并跳转对应的代码
2020/01/08 Javascript
Vue CLI4 Vue.config.js标准配置(最全注释)
2020/06/05 Javascript
ant-design-vue 时间选择器赋值默认时间的操作
2020/10/27 Javascript
[13:39]2014 DOTA2华西杯精英邀请赛 5 25 NewBee VS DK第一场
2014/05/26 DOTA
[48:00]EG vs LGD 2018国际邀请赛淘汰赛BO3 第二场 8.26
2018/08/29 DOTA
[40:03]RNG vs VG 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
Python3 适合初学者学习的银行账户登录系统实例
2017/08/08 Python
Django读取Mysql数据并显示在前端的实例
2018/05/27 Python
详解python中@的用法
2019/03/27 Python
django-rest-framework解析请求参数过程详解
2019/07/18 Python
基于python图像处理API的使用示例
2020/04/03 Python
Anthropologie英国:美国家喻户晓的休闲服装和家居产品品牌
2018/12/05 全球购物
Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?用contains来区分是否有重复的对象。还是都不用
2013/07/30 面试题
校园联欢晚会主持词
2014/03/17 职场文书
论文指导教师评语
2014/04/28 职场文书
如何书写公司员工保密协议?
2019/06/27 职场文书
Win11怎么修改电源模式?Win11修改电源模式的方法
2022/04/05 数码科技
Mysql查询时间区间日期列表,不会由于数据表数据影响
2022/04/19 MySQL