有许多实用程序只有一个选项可以作为其他实用程序的别名,如下所示:

$ python3 ./1.py --help
Usage: 1.py [OPTIONS]

Options:
  --format TEXT
  --long TEXT    Alias to --format=long_format
  --help         Show this message and exit.

我如何在点击中实现--long个选项,以便在轻松使用该选项时,点击自动设置--long=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(callback=<here>)家中,已经有ctx家可供 Select .我试着设置ctx.params["format"] = "long_format",但它不起作用.有没有更好的方法来设置@click.ption别名自动设置不同的选项?我试着阅读了Click源代码和文档,但没有找到任何相关的东西.

也就是说,如何实现以下@click.ption回调:

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()

基于下面这个令人惊叹的答案,我创造了这个:

def __alias_option_callback(
    aliased: Dict[str, Any],
    ctx: click.Context,
    param: click.Parameter,
    value: Any,
):
    """Callback called from alias_option option."""
    if value:
        for paramname, val in aliased.items():
            param = next(p for p in ctx.command.params if p.name == paramname)
            param.default = val

def alias_option(
    *param_decls: str,
    aliased: Dict[str, Any],
    **attrs: Any,
):
    """Add this to click options to have an alias for other options"""
    aliasedhelp = " ".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"Alias to {aliasedhelp}",
        callback=lambda *args: __alias_option_callback(aliased, *args),
        **attrs,
    )

@click.command()
# Auto generates help= and sets --format when used.
@alias_option("--long", aliased=dict(format="long_format"))
def cli():
   pass

它并不完美,因为它不能正确处理False,但适用于我有限的用例.

推荐答案

IIUC,您可以通过编程设置--format选项的默认值:

import argparse
from typing import Any, Optional

import click


def set_long(ctx, *_):
    for p in ctx.command.params:
        if p.name == "format":
            p.default = "long_format"


@click.command()
@click.option("--format", default="default_format")
@click.option(
    "--long", is_flag=True, help="Alias to --format=long_format", callback=set_long
)
def cli(**kwargs):
    args = argparse.Namespace(**kwargs)
    print(args.format)


cli()

调用python3 script.py --long将打印:

long_format

Python-3.x相关问答推荐

根据收件箱内部的值以行降序的特定顺序重新排序列

Gekko优化超出了方程式的界限(由于某种原因,会产生变量)

字符串块数组:如何根据一个数组中的元素对另一个数组中的元素进行分组

被多个\n拆分并保留

从Metacritic上通过网络擦除游戏数据的问题

Pandas 根据条件增加Dataframe列

如何将项目添加到Python中具有固定大小的列表列表中

如何将函数映射到所有命名元组的元素?

Python ** 用于负数

如何使用 regex sub 根据列表中的变量替换字符

spaCy 中的匹配模式返回空结果

ValueError:找不到子字符串,我做错了什么?

Python 错误:IndexError:字符串索引超出范围

Python中调用者函数的访问变量

TypeError:列表索引必须是整数或切片,而不是列表

如何将 cv2.imread 匹配到 keras image.img_load 输出

map 对象不是 JSON 可序列化的

将列表列表转换为Python中的字典字典

有没有办法在多个线程中使用 asyncio.Queue ?

在 PostgreSQL 上使用 SQLAlchemy 创建全文搜索索引