命令行模块——click(二)

命令行模块——click(二)

1.Click命令

命令是 Click 库中的核心部分,它们代表了我们可以在命令行中执行的不同操作。在 Click 中,我们可以通过使用 @click.command() 装饰器来定义一个命令,并使用函数体内的代码来实现该命令的功能。例如:

import click@click.command()
def hello():click.echo("Hello, world!")

在上面的例子中,我们使用 Click 的 @click.command() 装饰器来定义了一个名为 hello 的命令,该命令不接收任何参数,如果代码写在demo.py当执行python demo.py时,会输出“Hello, world!”的信息。一般来说,我们会给命令添加参数和选项,也就是在之前的文章中所写的那样。

2.Click命令组

命令组是 Click 库中用于组织一组相关命令的工具。它允许将一组命令作为一个整体进行操作,并且可以方便地进行嵌套和组合。在 Click 中,我们可以通过 click.group() 装饰器来定义一个命令组,并使用 @click.command() 装饰器来定义该组内的命令。

下面是一个使用命令组的示例,其中我们定义了一个名为 cli 的命令组,并将两个子命令 initstatus 添加到该组中:

import click@click.group()
def cli():pass@cli.command()
def init():click.echo("Initialized the database")@cli.command()
def status():click.echo("Status of the database")if __name__ == "__main__":cli()

当我们命令窗执行python demo.py init输出为:Initialized the database。在上面的代码中,我们首先使用 click.group() 装饰器定义了一个名为 cli 的命令组,然后使用 command() 方法为该组添加了两个子命令 initstatus。当用户在命令行中输入 python demo.py 时,程序会默认执行 cli 命令组中的逻辑,并按需调用子命令。

多组命令的情况:一个模块中包含多个命令组,也就是模块中定义多个装饰了 click.group() 的函数,每个函数对应一个命令组。同时,也可以在每个命令组下面定义多个子命令,使用 @click.command() 装饰器来为命令组添加子命令。

更加复杂的情况:

import click@click.group()
def cli():"""Main tool"""@cli.group()
def cmd():"""Command sub-group"""@cmd.command()
def init():"""Initialize"""print('Init')@cli.group()
def config():"""Configuration sub-group"""@config.group()
def network():"""Network configuration"""@network.command()
def ip():"""Set IP address"""print('Set IP')@network.command()
def subnet():"""Set subnet mask"""print('Set subnet mask')def main():cli()# cmd()# config()# network()if __name__ == '__main__':main()

在这个示例中,我们定义了一个命令行接口,包含:- 命令组cli作为主入口
- cli下面有两个子命令组cmd和config
- cmd下面有一个子命令init
- config下面又有一个子命令组network
- network下面有两个子命令ip和subnet所以整个命令行接口的结构如下:

在这里插入图片描述

这里调用的时候就用注意啦!从以上的结构上可以看出来,命令cmd和config是依附于cli的,所以在main中调用了cli,在命令窗中输入:python demo.py config network subnet,可以看到不用在写上cli,cli是默认执行的,只需要指明器子命令,子命令下的子命令即可。这就引发了我的好奇,是不是我在main中调用cmd和config可以默认执行呢?所以进行了尝试,在命令窗中运行了:python demo.py init,报错Error: No such command 'init',看来就算在main中直接吊用了cmd,cmd也不是像cli那样默认执行的,这个要注意。其他情况也是同理,就算是在main中调用了config也不能直接输入python demo.py network subnet,否则报错,调用subnet需要python demo.py config network subnet

再举一个例子说明一下:

import click@click.group()
def cli1():"""Main command line tool"""@cli1.group()  
def cli2():"""Sub command group"""@cli2.command()
def init():"""Initialize"""print('Init')@cli1.group()
def cli3():"""Other sub command group"""  @cli3.command()
def add():"""Add item"""print('Add')def main():cli1()cli2()cli3()if __name__ == '__main__':main()

在这个示例中,我们定义了:- 命令组cli1作为根命令组
- cli1下面有两个子命令组cli2和cli3
- cli2下面有子命令init
- cli3下面有子命令add

在main函数中,我们按嵌套结构注册了所有命令组:cli1 -> cli2 -> cli3

所以在命令行可以这样调用:

python file.py 
# 只调用cli1根命令组,等待子命令python file.py cli2 init
# cli1 -> cli2 -> init 
输出:Initpython file.py cli3 add  
# cli1 -> cli3 -> add
输出:Add 

以上就是命令组的一些知识梳理。

还有一点我在代码中遇到的这里补充一下。一个与click有关的装饰器@xx.result_callback(),其中xx是定义好的函数。具体举一个例子来说明一下这个装饰器的用法和作用。

import click@click.group()
# @click.option("--a", type=int)
# @click.option("--b", type=int)
@click.argument("a", type=int)
@click.argument("b", type=int)
def cli(**kwargs):pass@cli.result_callback()
def add(haha, a, b):c = a+bprint("Welcome!!!", c)@cli.command()
def end():click.echo("the end")if __name__ == "__main__":cli()

以上例子中@cli.result_callback(show_result)用于为命令定义结果回调函数。回调函数的就是不用专门调用,执行的时候是默认的。这里在学习它的时候遇到了一些问题,这里记录一下。首先使用回调函数的时候使用的是@click.group()装饰器,放在主函数前,其次,要回调的函数要是使用@xx.result_callback(),其中xx表示主函数名字,还用回调函数中的参数要在主函数前就用@click.option@click.argument就定义好,如果在回调函数前定义,会报错。最后,主函数要有子命令这个代码的子命令是end函数,使用前要用@cli.command()装饰器(如果没有写子命令,会报错)。回调函数中的参数是@click.option@click.argument定义好的,其实最开始这个回调程序我是这样写的:

 def add(a, b):c = a+bprint("Welcome!!!", c)

调用时python demo.py 2 20 end报错:TypeError: add() got multiple values for argument 'a'逻辑是对的为啥会出现这样的错误,很不理解。就查,但是跟这个关系都不太大。既然说是参数有问题,就鬼使神差的,我就这个函数中加了一个参数(这个参数之前也没有定义),就不报错了,但是不知道为啥。反正下次再使用回调函数的时候,再用出现这样的错误就知道咋改了。

以上就是我用到的关于click命令模块之后总结的东西。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部