You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用click库基于前序参数限制命令参数可选值?

可以用Click实现动态依赖前序参数的补全

当然可以实现,Click支持通过自定义补全函数来实现这种依赖前序参数的动态补全,不需要依赖静态的click.Choice。下面是完整的代码示例:

实现步骤

1. 编写工具类扫描目录文件

先实现一个ToolsFinder类,负责动态扫描目标目录D,提取工具名称和对应的版本:

import os
import re

class ToolsFinder:
    FILE_PATTERN = re.compile(r"^(?P<name>[^_]+)_(?P<version>[^_]+)\.zip$")
    TARGET_DIR = "/path/to/your/directory/D"  # 替换成实际目录路径

    @classmethod
    def get_all_tools(cls):
        """扫描目录,返回{name: [versions]}的字典"""
        tools = {}
        if not os.path.exists(cls.TARGET_DIR):
            return tools
        for filename in os.listdir(cls.TARGET_DIR):
            match = cls.FILE_PATTERN.match(filename)
            if match:
                name = match.group("name")
                version = match.group("version")
                if name not in tools:
                    tools[name] = []
                tools[name].append(version)
        # 对版本排序,可选
        for name in tools:
            tools[name].sort()
        return tools

    @classmethod
    def get_names(cls):
        """获取所有工具名称"""
        return list(cls.get_all_tools().keys())

    @classmethod
    def get_versions(cls, name):
        """根据工具名称获取对应的版本列表"""
        return cls.get_all_tools().get(name, [])

2. 实现带动态补全的Click命令

利用Click的autocompletion参数为每个参数指定自定义补全函数,其中版本参数的补全函数会通过上下文(ctx)获取已经输入的工具名称:

import click

def complete_tool_names(ctx, args, incomplete):
    """工具名称的补全函数"""
    all_names = ToolsFinder.get_names()
    return [name for name in all_names if name.startswith(incomplete)]

def complete_versions(ctx, args, incomplete):
    """版本的补全函数,依赖已输入的工具名称"""
    # 从上下文获取已经输入的name参数值
    tool_name = ctx.params.get("name")
    if not tool_name:
        return []
    all_versions = ToolsFinder.get_versions(tool_name)
    return [version for version in all_versions if version.startswith(incomplete)]

@click.command()
@click.argument("name", autocompletion=complete_tool_names)
@click.argument("version", autocompletion=complete_versions)
def install(name, version):
    """安装指定名称和版本的工具"""
    click.echo(f"准备安装 {name} 的 {version} 版本")
    # 这里添加实际的安装逻辑

if __name__ == "__main__":
    install()

关键说明

  • 每次触发补全时,complete_tool_names和complete_versions都会重新调用ToolsFinder扫描目录,确保候选值是实时更新的,新增/删除文件后不需要修改代码。
  • 版本补全函数通过ctx.params.get("name")获取用户已经输入的工具名称,只有当用户输入了有效的名称后,才会返回对应的版本候选。
  • 补全函数返回的列表会自动过滤掉和当前输入前缀不匹配的项(通过startswith(incomplete)),符合Tab补全的常规逻辑。

测试验证

  1. 执行mytool install <TAB>,会自动列出目录中所有工具名称(name1、name2、name3等)。
  2. 输入mytool install name2 <TAB>,会列出name2对应的所有版本(version1、version2等)。
  3. 新增name2_version3.zip和name4_version1.zip后,再次触发Tab补全,候选值会自动更新。

内容的提问来源于stack exchange,提问作者Kraal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 11:01:33