作者:HelloGitHub-Prodesire

HelloGitHub 的《讲解开源项目》系列,项目地址:https://github.com/HelloGitHub-Team/Article

一、前言

在上一篇文章中,我们初步掌握了 click 的简单用法,并了解到它与 argparsedocopt 的不同。接下来,将深入介绍 click 的各类用法,以让你能轻松打造复杂的命令行程序。

在概念上, click 把命令行分为 3 个组成:参数、选项和命令。

  • 参数 就是跟在命令后的除选项外的内容,比如 git add a.txt 中的 a.txt 就是表示文件路径的参数
  • 选项 就是以 --- 开头的参数,比如 -f--file
  • 命令 就是命令行的初衷了,比如 git 就是命令,而 git add 中的 add 则是 git 的子命令
本系列文章默认使用 Python 3 作为解释器进行讲解。
若你仍在使用 Python 2,请注意两者之间语法和库的使用差异哦~

二、参数

2.1 基本参数

基本参数 就是通过位置里指定参数值。

比如,我们可以指定两个位置参数 xy ,先添加的 x 位于第一个位置,后加入的 y 位于第二个位置。那么在命令行中输入 1 2的时候,分别对应到的就是 xy

@click.command()
@click.argument('x')
@click.argument('y')
def hello(x, y):
print(x, y)

2.2 参数类型

参数类型 就是将参数值作为什么类型去解析,默认情况下是字符串类型。我们可以通过 type 入参来指定参数类型。

click 支持的参数类型多种多样:

  • str / click.STRING 表示字符串类型,这也是默认类型
  • int / click.INT 表示整型
  • float / click.FLOAT 表示浮点型
  • bool / click.BOOL 表示布尔型。很棒之处在于,它会识别表示真/假的字符。对于 1yesytrue 会转化为 True0nonfalse 会转化为 False
  • click.UUID 表示 UUID,会自动将参数转换为 uuid.UUID 对象
  • click.FILE 表示文件,会自动将参数转换为文件对象,并在命令行结束时自动关闭文件
  • click.PATH 表示路径
  • click.Choice 表示选择选项
  • click.IntRange 表示范围选项

argparse 一样,click 也支持自定义类型,需要编写 click.ParamType 的子类,并重载 convert 方法。

官网提供了一个例子,实现了一个整数类型,除了普通整数之外,还接受十六进制和八进制数字, 并将它们转换为常规整数:

class BasedIntParamType(click.ParamType):
name = "integer" def convert(self, value, param, ctx):
try:
if value[:2].lower() == "0x":
return int(value[2:], 16)
elif value[:1] == "0":
return int(value, 8)
return int(value, 10)
except TypeError:
self.fail(
"expected string for int() conversion, got "
f"{value!r} of type {type(value).__name__}",
param,
ctx,
)
except ValueError:
self.fail(f"{value!r} is not a valid integer", param, ctx) BASED_INT = BasedIntParamType()

2.3 文件参数

在基本参数的基础上,通过指定参数类型,我们就能构建出各类参数。

文件参数 是非常常用的一类参数,通过 type=click.File 指定,它能正确处理所有 Python 版本的 unicode 和 字节,使得处理文件十分方便。

@click.command()
@click.argument('input', type=click.File('rb')) # 指定文件为二进制读
@click.argument('output', type=click.File('wb')) # 指定文件为二进制写
def inout(input, output):
while True:
chunk = input.read(1024) # 此时 input 为文件对象,每次读入 1024 字节
if not chunk:
break
output.write(chunk) # 此时 output 为文件对象,写入上步读入的内容

2.4 文件路径参数

文件路径参数 用来处理文件路径,可以对路径做是否存在等检查,通过 type=click.Path 指定。不论文件名是 unicode 还是字节类型,获取到的参数类型都是 unicode 类型。

@click.command()
@click.argument('filename', type=click.Path(exists=True)) # 要求给定路径存在,否则报错
def hello(filename):
click.echo(click.format_filename(filename))

如果文件名是以 - 开头,会被误认为是命令行选项,这个时候需要在参数前加上 -- 和空格,比如

$ python hello.py -- -foo.txt
-foo.txt

2.5 选择项参数

选择项参数 用来限定参数内容,通过 type=click.Choice 指定。

比如,指定文件读取方式限制为 read-onlyread-write

@click.command()
@click.argument('mode', type=click.Choice(['read-only', 'read-write']))
def hello(mode):
click.echo(mode)

2.6 可变参数

可变参数 用来定义一个参数可以有多个值,且能通过 nargs 来定义值的个数,取得的参数的变量类型为元组。

nargs=NN为一个数字,则要求该参数提供 N 个值。若 N-1 则接受提供无数量限制的参数,如:

@click.command()
@click.argument('foo', nargs=-1)
@click.argument('bar', nargs=1)
def hello(foo, bar):
pass

如果要实现 argparse 中要求参数数量为 1 个或多个的功能,则指定 nargs=-1required=True 即可:

@click.command()
@click.argument('foo', nargs=-1, required=True)
def hello(foo, bar):
pass

2.7 从环境变量读取参数

通过在 click.argument 中指定 envvar,则可读取指定名称的环境变量作为参数值,比如:

@click.command()
@click.argument('filename', envvar='FILENAME')
def hello(filename):
print(filename)

执行如下命令查看效果:

$ FILENAME=hello.txt python3 hello.py
hello.txt

而在 argparse 中,则需要自己从环境变量中读取。

三、小节

本文讲解了 click 中基本参数的用法,在此基础上介绍了各种类型的参数,最后说明了从环境变量中获取参数值的写法。

在下一篇文章中,我们来继续深入了解 click 的功能,看看它都支持什么样的“选项”。


『讲解开源项目系列』——让对开源项目感兴趣的人不再畏惧、让开源项目的发起者不再孤单。跟着我们的文章,你会发现编程的乐趣、使用和发现参与开源项目如此简单。欢迎留言联系我们、加入我们,让更多人爱上开源、贡献开源~

Python 命令行之旅:深入 click 之参数篇的更多相关文章

  1. Python 命令行之旅 —— 初探 argparse

    『讲解开源项目系列』启动--让对开源项目感兴趣的人不再畏惧.让开源项目的发起者不再孤单.跟着我们的文章,你会发现编程的乐趣.使用和发现参与开源项目如此简单.欢迎联系我们给我们投稿,让更多人爱上开源.贡 ...

  2. Python 命令行之旅:深入 click 之选项篇

    作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...

  3. Python 命令行之旅:深入 click 之子命令篇

    作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...

  4. Python 命令行之旅:深入 click 之增强功能

    作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...

  5. Python 命令行之旅:使用 click 实现 git 命令

    作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...

  6. Python 命令行之旅:使用 docopt 实现 git 命令

    作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...

  7. Python 命令行之旅 —— 深入 argparse (一)

    作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...

  8. Python 命令行之旅:深入 argparse(二)

    作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...

  9. Python 命令行之旅:使用 argparse 实现 git 命令

    作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...

随机推荐

  1. Python入门系列【附】进阶教程

    如题,本篇将讲解Python提升之路:Python作为语法简单易学的语言,入门容易精通却很难,这是共识,那么为什么会有这样的共识?精通Python的难度在哪里? Python拥有简单.形象.直观的语法 ...

  2. Flutter学习笔记(29)--Flutter如何与native进行通信

    如需转载,请注明出处:Flutter学习笔记(29)--Flutter如何与native进行通信 前言:在我们开发Flutter项目的时候,难免会遇到需要调用native api或者是其他的情况,这时 ...

  3. 你也可以写聊天程序 - C# Socket学习1

    简述 我们做软件工作的虽然每天都离不开网络,可网络协议细节却不是每个人都会接触和深入了解.我今天就来和大家一起学习下Socket,并写一个简单的聊天程序. 一些基础类 首先我们每天打开浏览器访问网页信 ...

  4. 刷新:重新发现.NET与未来

    微软在比尔·盖茨手中创立并崛起, 成为PC互联网时代的霸主,很多70,80后都有MVP Ediwang的体验: 当时的微软对我来说就是神的存在.因为我认识电脑到使用电脑的一切几乎都离不开这家伟大的公司 ...

  5. 决策树算法系列之一 ID3

    1 什么是决策树 通俗来说,决策树分类的思想类似于找对象 一个女孩的母亲要给这个女孩介绍男朋友 (分类问题.见或不见) 女孩有自己的一套标准 长相 收入 职业 见面与否 丑 高 某箭队经理 不见 中等 ...

  6. NoUniqueBeanDefinitionException常见异常!!

    Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of ...

  7. mac下编译openjdk8?so easy!

    写在最前面的话:建议第一次编译jdk的朋友,查阅任何博客都不如认真读一遍源码中的README-builds.html 环境:macOS High Sierra(10.13.5) 编译jdk:openj ...

  8. Linux快速入门

    一.Linux介绍 1.Linux是基于Unix的开源免费的操作系统 2.Linux的分类: (1)Linux根据市场需求不同,基本分为两个方向: 1)图形化界面版:注重用户体验,类似window操作 ...

  9. eclipse中的项目运行时不出现run as→java application选项

    eclipse中的运行java project时不出现run as→java application选项? 解决方案☞必须有正确的主方法,即public static void main(String ...

  10. Python3之多线程学习

    这里做一个自己复习多线程的笔记 Python中使用线程有两种方式:函数或者用类来包装线程对象. 函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程.语法如下: ...