使用Click(python)进行参数解析,如何自定义选项的处理,例如,如何将它们的所有参数存储在一个列表中?

2024-06-16 10:17:50 发布

您现在位置:Python中文网/ 问答频道 /正文

这个问题涉及Python的Click (v7.0+) library

我想设计一个具有多个选项的命令,所有这些选项都将给定的参数存储到一个中心列表中。以下是我希望它在用户端的外观:

$ myfoo --eat 'egg'  --drink 'water' 2  --eat 'chicken' --drink 'cola' 1

输出:

ate: egg
drank: water, 2 cup(s)
ate: chicken
drank: cola, 1 cup(s)

基本上,--eat--drink选项接受多个值。解析参数时,它们各自的所有参数都被编译成一个列表,命令对该列表进行迭代和操作(例如,逐行打印到stdout)

使用Click,这里是我的myfoo()命令的一个简单(且不起作用)实现:

import click

ACTIONS_LIST = []

def compile_actions(ctx=None, param=None, values=None):
    for v in values:
        d = {'type': param.name}
        if d['type'] == 'eat':
            d['item'] = v
        elif d['type'] == 'drink':
            d['item'] = v[0]
            d['amount'] = '%s cup(s)' % v[1]
        ACTIONS_LIST.append(d)


@click.command()
@click.option(
    '--eat',
    multiple=True,
    nargs=1,
    callback=compile_actions,
)
@click.option(
    '--drink',
    multiple=True,
    nargs=2,
    callback=compile_actions,
)
def myfoo(**kwargs):
    for a in ACTIONS_LIST:
        if a['type'] == 'eat':
            print(f"ate: {a['item']}")

        elif a['type'] == 'drink':
            print(f"drank: {a['item']}, {a['amount']}")

if __name__ == '__main__':
    myfoo()

无论如何,我上述实施的结果是:

$ myfoo --eat 'egg'  --drink 'water' 2  --eat 'chicken' --drink 'cola' 1
ate: egg
ate: chicken
drank: water, 2 cup(s)
drank: cola, 1 cup(s)

我想让选项回调函数(即compile_actions())在解析每个选项时按顺序处理它。但是当我们在回调函数中时,eatdrink的参数已经通过选项收集,然后进行处理

换句话说,ACTIONS_LIST,正如我天真地实现的那样,在传递给myfoo命令时,选项/值的顺序将不同。为了重申我的顶级示例输出,以下是我希望看到的处理顺序:

ate: egg
drank: water, 2 cup(s)
ate: chicken
drank: cola, 1 cup(s)

我假设选项回调不符合我的要求,那么我应该看什么呢?自定义Click.ParamType?自定义Click.Command?有趣的是,我知道如何在stdlib argparse中实现这一点,但在阅读文档时却无法理解如何在Click中实现这一点


Tags: 命令参数eggtype选项cupclickdrink