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

Python 号令行之旅:深切 click 之子号令篇 时候:2024-12-13 21:09:32 手机看文章

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

1、媒介

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

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

Click中很是主要的特征就是肆意嵌套号令行东西的概念,经由过程 Command[2] 和 Group[3] (现实上是 MultiCommand[4])来实现。

所谓号令组就是若干个号令(或哨子号令)的调集,同样成为多号令。

2.1 回调挪用

对一个通俗的号令来讲,回调产生在号令被履行的时辰。假如这个法式的实现中只有号令,那末回调老是会被触发,就像我们在上一篇文章及第出的所有示例一样。不外像 --help这类选项则会禁止进入回调。

对组和多个子号令来讲,环境略有分歧。回调凡是产生在子号令被履行的时辰:

@click.group() @click.option('--debug/--no-debug', default=False) def cli(debug): click.echo('Debug mode is %s' % ('on' if debug else 'off')) @cli.command() # @cli, not @click! def sync(): click.echo('Syncing')

履行结果以下:

Usage: tool.py [OPTIONS] COMMAND [ARGS]...Options: --debug / --no-debug --help Show this message and exit.Commands: sync美金 tool.py --debug syncDebug mode is onSyncing

在上面的示例中,我们将函数 cli界说为一个组,把函数 sync界说为这个组内的子号令。当我们挪用 tool.py --debug sync号令时,会顺次触发 cli和 sync的处置逻辑(也就是号令的回调)。

2.2 嵌套处置和上下文

从上面的例子可以看到,号令组 cli领受的参数和子号令 sync彼此自力。可是有时我们但愿在子号令中能获得到号令组的参数,这便可以用 Context[5] 来实现。

每当号令被挪用时,click会建立新的上下文,并链接到父上下文。凡是,我们是看不到上下文信息的。但我们可以经由过程 pass_context[6] 装潢器来显式让 click传递上下文,此变量会作为第一个参数进行传递。

@click.group() @click.option('--debug/--no-debug', default=False) @click.pass_context def cli(ctx, debug): # 确保 ctx.obj 存在而且是个 dict。(以防 `cli()` 指定 obj 为其他类型 ctx.ensure_object(dict) ctx.obj['DEBUG'] = debug @cli.command() @click.pass_context def sync(ctx): click.echo('Debug is %s' % (ctx.obj['DEBUG'] and 'on' or 'off')) if __name__ == '__main__': cli(obj={})

在上面的示例中:

经由过程为号令组 cli和子号令 sync指定装潢器 click.pass_context,两个函数的第一个参数都是 ctx上下文 在号令组 cli中,给上下文的 obj变量(字典)赋值 在子号令 sync中经由过程 ctx.obj['DEBUG']取得上一步的参数 经由过程这类体例完成了从号令组到子号令的参数传递 2.3 不利用号令来挪用号令组

默许环境下,挪用子号令的时辰才会挪用号令组。而有时你可能想直接挪用号令组,经由过程指定 click.group的 invoke_without_command=True来实现:

@click.group(invoke_without_command=True) @click.pass_context def cli(ctx): if ctx.invoked_subcommand is None: click.echo('I was invoked without subcommand') else: click.echo('I am about to invoke %s' % ctx.invoked_subcommand) @cli.command() def sync(): click.echo('The subcommand')

挪用号令有:

美金 toolI was invoked without subcommand美金 tool syncI am about to invoke syncThe subcommand

在上面的示例中,经由过程 ctx.invoked_subcommand来判定是不是由子号令触发,针对两种环境打印日记。

2.4 自界说号令组/多号令

除利用 click.group[7] 来界说号令组外,你还可以自界说号令组(也就是多号令),如许你便可以延迟加载子号令,这会很有效。

自界说多号令需要实现 list_commands和 get_command方式:

import click import osplugin_folder = os.path.join(os.path.dirname(__file__), 'commands') class MyCLI(click.MultiCommand): def list_commands(self, ctx): rv = [] # 号令名称列表 for filename in os.listdir(plugin_folder): if filename.endswith('.py'): rv.append(filename[:-3]) rv.sort() return rv def get_command(self, ctx, name): ns = {} fn = os.path.join(plugin_folder, name + '.py') # 号令对应的 Python 文件 with open(fn) as f: code = compile(f.read(), fn, 'exec') eval(code, ns, ns) return ns['cli']cli = MyCLI(help='This tool\'s subcommands are loaded from a ' 'plugin folder dynamically.') # 等价体例是经由过程 click.command 装潢器,指定 cls=MyCLI # @click.command(cls=MyCLI) # def cli(): # pass if __name__ == '__main__': cli()
2.5 归并号令组/多号令

当有多个号令组,每一个号令组中有一些号令,你想把所有的号令归并在一个调集中时,click.CommandCollection就派上了用处:

@click.group() def cli1(): pass @cli1.command() def cmd1(): """Command on cli1""" @click.group() def cli2(): pass @cli2.command() def cmd2(): """Command on cli2""" cli = click.CommandCollection(sources=[cli1, cli2]) if __name__ == '__main__': cli()

挪用号令有:

美金 cli --help Usage: cli [OPTIONS] COMMAND [ARGS]...Options: --help Show this message and exit.Commands: cmd1 Command on cli1 cmd2 Command on cli2

从上面的示例可以看出,cmd1和 cmd2别离属在 cli1和 cli2,经由过程 click.CommandCollection可以将这些子号令归并在一路,将其能力供给个统一个号令法式。

Tips:假如多个号令组中界说了一样的子号令,那末取第一个号令组中的子号令。

2.6 链式号令组/多号令

有时单级子号令可能知足不了你的需求,你乃至但愿能有多级子号令。典型地,setuptools包中就撑持多级/链式子号令:setup.py sdist bdist_wheel upload。在 click 3.0 以后,实现链式号令组变得很是简单,只需在 click.group中指定 chain=True:

@click.group(chain=True) def cli(): pass @cli.command('sdist') def sdist(): click.echo('sdist called') @cli.command('bdist_wheel') def bdist_wheel(): click.echo('bdist_wheel called')

挪用号令则有:

美金 setup.py sdist bdist_wheelsdist calledbdist_wheel called
2.7 号令组/多号令管道

链式号令组中一个常见的场景就是实现管道,如许在上一个号令处置好后,可将成果传给下一个号令处置。

实现号令组管道的要点是让每一个号令返回一个处置函数,然后编写一个总的管道调剂函数(并由 MultiCommand.resultcallback()装潢):

@click.group(chain=True, invoke_without_command=True) @click.option('-i', '--input', type=click.File('r')) def cli(input): pass @cli.resultcallback() def process_pipeline(processors, input): iterator = (x.rstrip('\r\n') for x in input) for processor in processors: iterator = processor(iterator) for item in iterator: click.echo(item) @cli.command('uppercase') def make_uppercase(): def processor(iterator): for line in iterator: yield line.upper() return processor @cli.command('lowercase') def make_lowercase(): def processor(iterator): for line in iterator: yield line.lower() return processor @cli.command('strip') def make_strip(): def processor(iterator): for line in iterator: yield line.strip() return processor

在上面的示例中:

将 cli界说为了链式号令组,而且指定 invoke_without_command=True,也就意味着可以不传子号令来触发号令组 界说了三个号令处置函数,别离对应 uppercase、lowercase和 strip号令 在管道调剂函数 process_pipeline中,将输入 input酿成生成器,然后挪用处置函数(现实输入几个号令,就有几个处置函数)进行处置 2.8 笼盖默许值

默许环境下,参数的默许值是从经由过程装潢器参数 default界说。我们还可以经由过程 Context.default_map上下文字典来笼盖默许值:

@click.group() def cli(): pass @cli.command() @click.option('--port', default=8000) def runserver(port): click.echo('Serving on http://127.0.0.1:%d/' % port) if __name__ == '__main__': cli(default_map={ 'runserver': { 'port': 5000 } })

在上面的示例中,经由过程在 cli中指定 default_map变可笼盖号令(一级键)的选项(二级键)默许值(二级键的值)。

我们还可以在 click.group中指定 context_settings来到达一样的目标:

CONTEXT_SETTINGS = dict( default_map={'runserver': {'port': 5000}}) @click.group(context_settings=CONTEXT_SETTINGS) def cli(): pass @cli.command() @click.option('--port', default=8000) def runserver(port): click.echo('Serving on http://127.0.0.1:%d/' % port) if __name__ == '__main__': cli()

挪用号令则有:

美金 cli runserverServing on http://127.0.0.1:5000/
3、总结

本文起首介绍了号令的回调挪用、上下文,再进一步介绍号令组的自界说、归并、链接、管道等功能,领会到了 click的壮大。而号令组中加倍高阶的能力(如号令返回值[8])则可看官方文档进一步领会。

我们经由过程介绍 click 的参数、选项和号令已可以或许完全实现号令行法式的所有功能。而 click 还为我们供给了很多锦上添花的功能,好比适用东西、参数主动补全等,我们将鄙人节具体介绍。

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

上一篇:开云-【IC技术圈成员文章】异步电路碎碎念(六)手撕打拍同步器 下一篇:开云-RK3576来了值得买吗?看看他怎么说