如何在Python Click中实现选项别名,通过回调设置目标参数
在Click中实现选项别名的最优方式
很多工具支持将一个选项作为其他选项的别名,例如执行--help后显示的效果:
$ python3 ./1.py --help Usage: 1.py [OPTIONS] Options: --format TEXT --long TEXT Alias to --format=long_format --help Show this message and exit.
我需要在Click中实现--long选项,让用户使用它时自动将--format的值设为long_format。
我曾尝试用全局变量来覆盖参数,代码如下:
import argparse from typing import Any, Optional import click PARAMS = {} def set_param( opt: str, val: Any, ctx: click.Context, param: Optional[click.Parameter], value: Any ): if value: PARAMS[opt] = val @click.command() @click.option("--format", default="default_format") @click.option( "--long", is_flag=True, help="Alias to --format=long_format", callback=lambda *args: set_param("format", "long_format", *args), ) def cli(**kwargs): args = argparse.Namespace(**{**kwargs, **PARAMS}) print(args.format) cli()
但我发现,虽然@click.option的回调里能拿到ctx对象,但直接修改ctx.params["format"] = "long_format"并没有效果。我查过Click的源码和官方文档,没找到相关的实现说明,想知道有没有更优的实现方式?
换个说法,我希望在--long选项的回调里直接完成--format=long_format的设置,就像下面代码里的疑问部分:
import argparse from typing import Any, Optional import click @click.command() @click.option("--format", default="default_format") @click.option( "--long", is_flag=True, help="Alias to --format=long_format", callback=lambda *args: "How to set --format=long_format from here?", ) def cli(**kwargs): args = argparse.Namespace(**{**kwargs, **PARAMS}) print(args.format) cli()
我的实现方案
基于参考的优质回答,我编写了以下代码:
from typing import Dict, Any import click def __alias_option_callback( aliased: Dict[str, Any], ctx: click.Context, param: click.Parameter, value: Any, ): """别名选项的回调函数""" if value: for paramname, val in aliased.items(): target_param = next(p for p in ctx.command.params if p.name == paramname) target_param.default = val def alias_option( *param_decls: str, aliased: Dict[str, Any], **attrs: Any, ): """为Click命令添加选项别名的装饰器""" aliased_help = " ".join( "--" + k.replace("_", "-") + ("" if v is True else f"={v}" if isinstance(v, int) else f"={v!r}") for k, v in aliased.items() ) return click.option( *param_decls, is_flag=True, help=f"等价于 {aliased_help}", callback=lambda *args: __alias_option_callback(aliased, *args), **attrs, ) @click.command() # 自动生成帮助文本,使用--long时自动设置--format的值 @alias_option("--long", aliased=dict(format="long_format")) def cli(): pass
这段代码目前还不能完美处理False值的情况,但已经满足我的基本需求。后续我对代码做了进一步修复,将其整合到了我开发的clickdc pip包中。
内容的提问来源于stack exchange,提问作者KamilCuk
相关产品推荐
相关产品推荐

