开云-Python 命令行之旅:深入 click 之选项篇

Python 号令行之旅:深切 click 之选项篇 时候:2024-12-13 21:05:40 手机看文章

扫描二维码随时随地手机看文章

1、媒介

在上一篇文章中,我们介绍了 click中的“参数”,本文将继续深切领会 click,侧重讲授它的“选项”。

本系列文章默许利用 Python 3 作为注释器进行讲授。若你仍在利用 Python 2,请留意二者之间语法和库的利用差别哦~
2、选项

经由过程 click.option可以给号令增添选项,并经由过程设置装备摆设函数的参数来设置装备摆设分歧功能的选项。

2.1 给选项定名

click.option中的号令法则可参考参数名称[2]。它接管的前两个参数为长、短选项(挨次随便),此中:

长选项以 “--” 开首,好比 “--string-to-echo” 短选项以 “-” 开首,好比 “-s”

第三个参数为选项参数的名称,假如不指定,将会利用长选项的下划线情势名称:

@click.command() @click.option('-s', '--string-to-echo') def echo(string_to_echo): click.echo(string_to_echo)

显示指定为 string

@click.command() @click.option('-s', '--string-to-echo', 'string') def echo(string): click.echo(string)
2.2 根基值选项

值选项长短经常用的选项,它接管一个值。假如在号令行中供给了值选项,则需要供给对应的值;反之则利用默许值。若没在 click.option中指定默许值,则默许值为 None,且该选项的类型为 STRING[3];反之,则选项类型为默许值的类型。

好比,供给默许值为 1,则选项类型为 INT[4]:

@click.command() @click.option('--n', default=1) def dots(n): click.echo('.' * n)

假如要求选项为必填,则可指定 click.option的 required=True:

@click.command() @click.option('--n', required=True, type=int) def dots(n): click.echo('.' * n)

假如选项名称和 Python 中的要害字冲突,则可以显式的指定选项名称。好比将 --from的名称设置为 from_:

@click.command() @click.option('--from', '-f', 'from_') @click.option('--to', '-t') def reserved_param_name(from_, to): click.echo(f'from {from_} to {to}')

假如要在帮忙中显式默许值,则可指定 click.option的 show_default=True:

@click.command() @click.option('--n', default=1, show_default=True) def dots(n): click.echo('.' * n)

在号令行中挪用则有:

美金 dots --help Usage: dots [OPTIONS]Options: --n INTEGER [default: 1] --help Show this message and exit.
2.3 多值选项

有时,我们会但愿号令行中一个选项能领受多个值,经由过程指定 click.option中的 nargs参数(必需是年夜在等在 0)。如许,领受的多值选项就会酿成一个元组。

好比,鄙人面的示例中,当经由过程 --pos指定多个值时,pos变量就是一个元组,里面的每一个元素是一个 float:

@click.command() @click.option('--pos', nargs=2, type=float) def findme(pos): click.echo(pos)

在号令行中挪用则有:

美金 findme --pos 2.0 3.0(1.0, 2.0)

有时,经由过程统一选项指定的多个值得类型可能分歧,这个时辰可以指定 click.option中的 type=(类型1, 类型2, ...)来实现。而因为元组的长度同时暗示了值的数目,所以就不必指定 nargs参数。

@click.command() @click.option('--item', type=(str, int)) def putitem(item): click.echo('name=%s id=%d' % item)

在号令行中挪用则有:

美金 putitem --item peter 1338name=peter id=1338
2.4 多选项

分歧在多值选项是经由过程一个选项指定多个值,多选项则是利用多个不异选项别离指定值,经由过程 click.option中的 multiple=True来实现。

当我们界说以下多选项:

@click.command() @click.option('--message', '-m', multiple=True) def commit(message): click.echo('\n'.join(message))

即可以指定肆意数目个选项来指定值,获得到的 message是一个元组:

美金 commit -m foo -m bar --message bazfoobarbaz
2.5 计值选项

有时我们可能需要取得选项的数目,那末可以指定 click.option中的 count=True来实现。

最多见的利用场景就是指定多个 --verbose或 -v选项来暗示输出内容的具体水平。

@click.command() @click.option('-v', '--verbose', count=True) def log(verbose): click.echo(f'Verbosity: {verbose}')

在号令行中挪用则有:

美金 log -vvvVerbosity: 3

经由过程上面的例子,verbose就是数字,暗示 -v选项的数目,由此可以进一步利用该值来节制日记的具体水平。

2.6 布尔选项

布尔选项用来暗示真或假,它有多种实现体例:

经由过程 click.option的 is_flag=True参数来实现:
import sys @click.command() @click.option('--shout', is_flag=True) def info(shout): rv = sys.platform if shout: rv = rv.upper() + '!!!!111' click.echo(rv)

在号令行中挪用则有:

美金 info --shoutLINUX!!!!111
经由过程在 click.option的选项界说中利用 /分隔暗示真假两个选项来实现:
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 --shoutLINUX!!!!111美金 info --no-shoutlinux

在 Windows 中,一个选项可以以 /开首,如许就会真假选项的分隔符冲突了,这个时辰可使用 ;进行分隔:

@click.command() @click.option('/debug;/no-debug') def log(debug): click.echo(f'debug={debug}') if __name__ == '__main__': log()

在 cmd 中挪用则有:

 log /debugdebug=True
2.7 特征切换选项

所谓特征切换就是切换统一个操尴尬刁难象的分歧特征,好比指定 --upper就让输出年夜写,指定 --lower就让输出小写。这么来看,布尔值实际上是特征切换的一个特例。

要实现特征切换选项,需要让多个选项都有不异的参数名称,而且界说它们的标识表记标帜值 flag_value:

import sys @click.command() @click.option('--upper', 'transformation', flag_value='upper', default=True) @click.option('--lower', 'transformation', flag_value='lower') def info(transformation): click.echo(getattr(sys.platform, transformation)())

在号令行中挪用则有:

美金 info --upperLINUX美金 info --lowerlinux美金 infoLINUX

在上面的示例中,--upper和 --lower都有不异的参数值 transformation:

当指定 --upper时,transformation就是 --upper选项的标识表记标帜值 upper 当指定 --lower时,transformation就是 --lower选项的标识表记标帜值 lower

进而便可以做进一步的营业逻辑处置。

2.8 选择项选项

选择项选项和 上篇文章中介绍的 选择项参数近似,只不外是限制选项内容,照旧是经由过程 type=click.Choice实现。另外,case_sensitive=False还可以疏忽选项内容的巨细写。

@click.command() @click.option('--hash-type', type=click.Choice(['MD5', 'SHA1'], case_sensitive=False)) def digest(hash_type): click.echo(hash_type)

在号令行中挪用则有:

美金 digest --hash-type=MD5MD5美金 digest --hash-type=md5MD5美金 digest --hash-type=fooUsage: digest [OPTIONS]Try "digest --help" for help.Error: Invalid value for "--hash-type": invalid choice: foo. (choose from MD5, SHA1)美金 digest --help Usage: digest [OPTIONS]Options: --hash-type [MD5|SHA1] --help Show this message and exit.
2.9 提醒选项

顾名思义,当供给了选项却没有供给对应的值时,会提醒用户输入值。这类交互式的体例会让号令行变得加倍友爱。经由过程指定 click.option中的 prompt可以实现。

当 prompt=True时,提醒内容为选项的参数名称
@click.command() @click.option('--name', prompt=True) def hello(name): click.echo(f'Hello {name}!')

在号令行挪用则有:

美金 hello --name=JohnHello John!美金 helloName: JohnHello John!
当 prompt='Your name please'时,提醒内容为指定内容
@click.command() @click.option('--name', prompt='Your name please') def hello(name): click.echo(f'Hello {name}!')

在号令行中挪用则有:

美金 helloYour name please: JohnHello John!

基在提醒选项,我们还可以指定 hide_input=True来埋没输入,confirmation_prompt=True来让用户进行二次输入,这很是合适输入暗码的场景。

@click.command() @click.option('--password', prompt=True, hide_input=True, confirmation_prompt=True) def encrypt(password): click.echo(f'Encrypting password to {password.encode("rot13")}')

固然,也能够直接利用 click.password_option:

@click.command() @click.password_option() def encrypt(password): click.echo(f'Encrypting password to {password.encode("rot13")}')

我们还可以给提醒选项设置默许值,经由过程 default参数进行设置,假如被设置为函数,则可以实现动态默许值。

@click.command() @click.option('--username', prompt=True, default=lambda: os.environ.get('USER', '')) def hello(username): print("Hello,", username)

详情请浏览 Dynamic Defaults for Prompts[5]。

2.10 规模选项

假如但愿选项的值在某个规模内,便可以利用规模选项,经由过程指定 type=click.IntRange来实现。它有两种模式:

默许模式(非强迫模式),假如值不在区间规模内将会激发一个毛病。如 type=click.IntRange(0, 10)暗示规模是 [0, 10],跨越该规模报错 强迫模式,假如值不在区间规模内,将会强迫拔取一个区间邻近值。如 click.IntRange(0, None, clamp=True)暗示规模是 [0, +∞),小在 0 则取 0,年夜在 20 则取 20。此中 None暗示没有限制
@click.command() @click.option('--count', type=click.IntRange(0, None, clamp=True)) @click.option('--digit', type=click.IntRange(0, 10)) def repeat(count, digit): click.echo(str(digit) * count) if __name__ == '__main__': repeat()

在号令行中挪用则有:

美金 repeat --count=1000 --digit=555555555555555555555美金 repeat --count=1000 --digit=12Usage: repeat [OPTIONS]Error: Invalid value for "--digit": 12 is not in the valid range of 0 to 10.
2.11 回和谐优先

回调经由过程 click.option中的 callback可以指定选项的回调,它会在该选项被解析后挪用。回调函数的签名以下:

def callback(ctx, param, value): pass 

此中:

ctx 是号令的上下文 click.Context[6] param 为选项变量 click.Option[7] value 为选项的值

利用回调函数可以完成额外的参数校验逻辑。好比,经由过程 --rolls 的选项来指定摇骰子的体例,内容为“{N}d{M}”,暗示 M 面的骰子摇 N 次,N 和 M 都是数字。在真实的处置 rolls 前,我们需要经由过程回调函数来校验它的格局:

def validate_rolls(ctx, param, value): try: rolls, dice = map(int, value.split('d', 2)) return (dice, rolls) except ValueError: raise click.BadParameter('rolls need to be in format NdM') @click.command() @click.option('--rolls', callback=validate_rolls, default='1d6') def roll(rolls): click.echo('Rolling a %d-sided dice %d time(s)' % rolls)

如许,当我们输入毛病格局时,变会校验欠亨过:

美金 roll --rolls=42Usage: roll [OPTIONS]Error: Invalid value for "--rolls": rolls need to be in format NdM

输入准确格局时,则正常输出信息:

美金 roll --rolls=2d12Rolling a 12-sided dice 2 time(s)

优先经由过程 click.option中的 is_eager可让该选项成为优先选项,这意味着它会先在所有选项处置。

操纵回和谐优先选项,我们便可以很好地实现 --version选项。非论号令行中写了几多选项和参数,只要包括了 --version,我们就但愿它打印版本就退出,而不履行其他选项的逻辑,那末就需要让它成为优先选项,而且在回调函数中打印版本。

另外,在 click中每一个选项都对应到号令处置函数的同名参数,假如不想把该选项传递处处理函数中,则需要指定 expose_value=True,在是有:

def print_version(ctx, param, value): if not value or ctx.resilient_parsing: return click.echo('Version 1.0') ctx.exit() @click.command() @click.option('--version', is_flag=True, callback=print_version, expose_value=False, is_eager=True) def hello(): click.echo('Hello World!')

固然 click供给了便捷的 click.version_option来实现 --version:

@click.command() @click.version_option(version='0.1.0') def hello(): pass 
2.12 Yes 选项

基在前面的进修,我们可以实现 Yes 选项,也就是对某些操作,不供给 --yes则进行二次确认,供给了则直接操作:

def abort_if_false(ctx, param, value): if not value: ctx.abort() @click.command() @click.option('--yes', is_flag=True, callback=abort_if_false, expose_value=False, prompt='Are you sure you want to drop the db?') def dropdb(): click.echo('Dropped all tables!')

固然 click供给了便捷的 click.confirmation_option来实现 Yes 选项:

@click.command() @click.confirmation_option(prompt='Are you sure you want to drop the db?') def dropdb(): click.echo('Dropped all tables!')

在号令行中挪用则有:

美金 dropdbAre you sure you want to drop the db? [y/N]: nAborted!美金 dropdb --yesDropped all tables!
2.11 其他加强功能

click撑持从情况中读取选项的值,这是 argparse所不撑持的,可参阅官方文档的 Values from Environment Variables[8] 和 Multiple Values from Environment Values[9]。

click撑持指定选项前缀,你可以不利用 -作为选项前缀,还可以使用 +或 /,固然在一般环境下其实不建议这么做。详情参阅官方文档的 Other Prefix Characters[10]

3、总结

可以看出,click对号令行选项的撑持很是丰硕和壮大,除撑持 argarse所撑持的所有选项类型外,还供给了诸如 计值选项、特征切换选项、提醒选项等更丰硕的选项类型。另外,还供给了从情况中读变量等便利易用的加强功能。的确就是开辟号令行法式的利器。

鄙人篇文章中,我们侧重介绍下 click的号令和组,这可是实现它的主要特征(肆意嵌套号令)的体例。

欲知详情,请下载word文档 下载文档

上一篇:开云-FPGA 上使用 SVM 进行图像处理 下一篇:开云-为何来复式收音机中都是用倍压检波?