Commands and Groups
Click最重要的特性,就是命令行任意嵌套;通过Command和Group(即MultiCommand)实现;
回调
普通命令中,当命令执行时同时执行回调;
如果命令行只涉及一个脚本,回调就会立即执行;除非参数阻止这一行为,如--help
参数;
在多命令情况下,执行子命令时同时执行回调(除非此行为被改变);
实例
import click
@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, 不是@click,加入命令组cli
def sync():
click.echo('Syncing')
if __name__ == '__main__':
cli()
运行
$ python test.py --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...
...
$ python test.py --debug sync
OPTIONS 传递给test.py的主命令cli;
ARGS 传递给子命令COMMAND;
传递参数
Click严格区分命令和子命令的参数;参数要跟在相应命令的后面;
以--help
为例
- tool.py --help 返回主命令的帮助
- tool.py sub --help 返回子命令的帮助
嵌套处理和上下文
修饰命令
带without command的组
自定义多命令
当需要从某个目录(插件目录)动态加载子命令时;
自定义多命令,继承自click.MultiCommand类,并实现list_commands()和get_command()
实例
import click
import os
plugin_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')
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.')
if __name__ == '__main__':
cli()
自定义类,也可当成修饰器使用
@click.command(cls=MyCLI)
def cli():
pass