装饰在单击命令之上

car*_*mom 6 python command-line-arguments python-3.x python-decorators python-click

我正在尝试装饰一个已经由@click命令行装饰和调用的函数。

大写输入的正常装饰可能如下所示:

标准装饰.py

def capitalise_input(f):
    def wrapper(*args):
        args = (args[0].upper(),)
        f(*args)
    return wrapper

@capitalise_input
def print_something(name):
    print(name)

if __name__ == '__main__':
    print_something("Hello")
Run Code Online (Sandbox Code Playgroud)

然后从命令行:

$ python standard_decoration.py
HELLO
Run Code Online (Sandbox Code Playgroud)

单击文档中的第一个示例如下所示:

你好.py

import click

@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
              help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello %s!' % name)

if __name__ == '__main__':
    hello()
Run Code Online (Sandbox Code Playgroud)

从命令行运行时:

$ python hello.py --count=3
Your name: John
Hello John!
Hello John!
Hello John!
Run Code Online (Sandbox Code Playgroud)
  1. 应用修饰器的正确方法是什么,该修饰器修改此点击装饰函数的输入,例如使其像上面一样大写?

  2. 一旦一个函数被 click 修饰,那么它所拥有的任何位置参数都被转换为关键字参数是真的吗?似乎它与'--count'参数函数中的字符串相匹配,然后装饰函数中的顺序似乎不再重要。

Mat*_*ttK 8

Harvey 的回答不适用于命令组。实际上,这将用 'wrapper' 替换 'hello' 命令,这不是我们想要的。而是尝试类似的事情:

from functools import wraps

def test_decorator(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        kwargs['name'] = kwargs['name'].upper()
        return f(*args, **kwargs)
    return wrapper
Run Code Online (Sandbox Code Playgroud)


Har*_*vey 4

看来 click 传递了关键字参数。这应该有效。我认为它需要是第一个装饰器,即在所有单击方法完成后调用它。

def capitalise_input(f):
    def wrapper(**kwargs):
        kwargs['name'] = kwargs['name'].upper()
        f(**kwargs)
    return wrapper


@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
              help='The person to greet.')
@capitalise_input
def hello(count, name):
    ....
Run Code Online (Sandbox Code Playgroud)

您还可以尝试类似的方法来具体说明要大写的参数:

def capitalise_input(key):
    def decorator(f):
        def wrapper(**kwargs):
            kwargs[key] = kwargs[key].upper()
            f(**kwargs)
        return wrapper
    return decorator

@capitalise_input('name')
def hello(count, name):
Run Code Online (Sandbox Code Playgroud)