Python 命令行之旅:深入 click 之参数篇

Stella981
• 阅读 553

👆 “Python猫” ,一个值得加星标的公众号

花下猫语: 处理命令行任务时,click 应该是最优雅的实现方法。今天继续分享这个系列的第二篇。另外还值得关注一点,这个库把装饰器用得炉火纯青,学习装饰器的话,这是一个很好的参考对象。

Python 命令行之旅:深入 click 之参数篇

剧照 | 《奇葩说》

作者:HelloGitHub-Prodesire

涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库[1]

击本文最下方的“阅读原文”即可获取

一、前言

在上一篇文章中,我们初步掌握了 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.pyhello.txt

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

三、小节

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

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

参考资料

[1] HelloGitHub-Team 仓库:  https://github.com/HelloGitHub-Team/Article

Python 命令行之旅:深入 click 之参数篇

优质文章,推荐阅读:

Python 中 -m 的典型用法、原理解析与发展演变

如何优雅高效地节省内存?官方给出了 12 个经典用法

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

当谈论迭代器时,我谈些什么?

Python 命令行之旅:深入 click 之参数篇

感谢创作者的好文Python 命令行之旅:深入 click 之参数篇

本文分享自微信公众号 - Python猫(python_cat)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Stella981 Stella981
2年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
2年前
Python 协程与 Go 协程的区别(二)
👆“Python猫”,一个值得加星标的公众号花下猫语:今天继续分享协程系列的第二篇。万字长文,收藏起来慢慢读吧。PS:原文中有挺多参考链接,微信不能很好保留。故建议阅读原文。作者:lgj\_bky(经作者授权转载)原文:https://www.cnblogs.com/lgjbky/p/10838035.html写在前面
Stella981 Stella981
2年前
200的大额人民币即将面世?央行:Yes!
点击上方蓝字关注我们!(https://oscimg.oschina.net/oscnet/2a1c2ac00bf54458a78c48a6c2e547d5.png)点击上方“印象python”,选择“星标”公众号重磅干货,第一时间送达!!(
可莉 可莉
2年前
200的大额人民币即将面世?央行:Yes!
点击上方蓝字关注我们!(https://oscimg.oschina.net/oscnet/2a1c2ac00bf54458a78c48a6c2e547d5.png)点击上方“印象python”,选择“星标”公众号重磅干货,第一时间送达!!(
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这