对带有可变参数的类使用python click命令 [英] Use python click command with a class with variadic arguments

查看:216
本文介绍了对带有可变参数的类使用python click命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用先前未知数量的参数初始化的类,我希望使用python click软件包在cli上完成该操作.我的问题是我无法初始化它并运行单击命令:

I have a class that gets initialized with a previously unknown number of arguments and I want it to be done on cli using python click package. My issue is that I can't manage to initialize it and run a click command:

$ python mycode.py arg1 arg2 ... argN click_command

因为带有可变参数选项nargs=-1,所以单击时无法将click_command识别为命令.

because with variadic arguments option nargs=-1 click don't recognize the click_command as a command.

如何输入N个参数,然后使用click运行命令?

How can I input N args and then run a command using click?

设置一定数量的参数(如nargs=5)可以解决命令丢失的问题,但必须在命令前输入5个args.

Setting a defined number of arguments, like nargs=5, solves the issue of missing command but obligates me to input 5 args before my command.

import click

class Foo(object):
    def __init__(self, *args):
        self.args = args

    def log(self):
        print('self.args:', self.args)

pass_foo = click.make_pass_decorator(Foo)

@click.group()
@click.argument('myargs', nargs=-1)
@click.pass_context
def main(ctx, myargs):
    ctx.obj = Foo(myargs)
    print("arguments: ", myargs)

@main.command()
@pass_foo
def log(foo):
    foo.log()

main()

我希望在将N个参数传递给我的Foo()类之后能够运行click命令,以便我可以对其进行初始化并在cli上作为命令运行其log()方法,但是输出为:

I expect to be able to run a click command after passing N args to my Foo() class so I can initialize it and run its log() method as a command on cli, but the output is:

错误:缺少命令

Error: Missing command

推荐答案

我不确定您要做什么是解决此问题的最佳方法.我认为将可变参数作为命令的后面会更合逻辑,并且绝对与单击的工作方式保持一致.但是,您可以执行以下操作:

I am not entirely sure what you are trying to do is the best way to approach this problem. I would think that placing the variadic arguments after the command would be a bit more logical, and would definitely more align with the way click works. But, you can do what you are after with this:

class CommandAfterArgs(click.Group):

    def parse_args(self, ctx, args):
        parsed_args = super(CommandAfterArgs, self).parse_args(ctx, args)
        possible_command = ctx.params['myargs'][-1]
        if possible_command in self.commands:
            ctx.protected_args = [possible_command]
            ctx.params['myargs'] = ctx.params['myargs'][:-1]

        elif possible_command in ('-h', '--help'):
            if len(ctx.params['myargs']) > 1 and \
                    ctx.params['myargs'][-2] in self.commands:
                ctx.protected_args = [ctx.params['myargs'][-2]]
                parsed_args = ['--help']
                ctx.params['myargs'] = ctx.params['myargs'][:-2]
                ctx.args = [possible_command]

        return parsed_args

使用自定义类:

然后使用自定义类,将其作为cls参数传递给组装饰器,如下所示:

Using Custom Class:

Then to use the custom class, pass it as the cls argument to the group decorator like:

@click.group(cls=CommandAfterArgs)
@click.argument('myargs', nargs=-1)
def main(myargs):
    ...

测试代码:

import click

class Foo(object):
    def __init__(self, *args):
        self.args = args

    def log(self):
        print('self.args:', self.args)


pass_foo = click.make_pass_decorator(Foo)


@click.group(cls=CommandAfterArgs)
@click.argument('myargs', nargs=-1)
@click.pass_context
def main(ctx, myargs):
    ctx.obj = Foo(*myargs)
    print("arguments: ", myargs)


@main.command()
@pass_foo
def log(foo):
    foo.log()


if __name__ == "__main__":
    commands = (
        'arg1 arg2 log',
        'log --help',
        '--help',
    )

    import sys, time

    time.sleep(1)
    print('Click Version: {}'.format(click.__version__))
    print('Python Version: {}'.format(sys.version))
    for cmd in commands:
        try:
            time.sleep(0.1)
            print('-----------')
            print('> ' + cmd)
            time.sleep(0.1)
            main(cmd.split())

        except BaseException as exc:
            if str(exc) != '0' and \
                    not isinstance(exc, (click.ClickException, SystemExit)):
                raise

结果:

Click Version: 6.7
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> arg1 arg2 log
arguments:  ('arg1', 'arg2')
self.args: ('arg1', 'arg2')
-----------
> log --help
arguments:  ()
Usage: test.py log [OPTIONS]

Options:
  --help  Show this message and exit.
-----------
> --help
Usage: test.py [OPTIONS] [MYARGS]... COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  log

这篇关于对带有可变参数的类使用python click命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆