当@ click.option用于将命令行参数传递给函数时,如何返回值?

时间:2014-10-07 23:19:34

标签: python python-decorators

我正在尝试使用click python包将命令行参数传递给函数。官方文档中的示例如解释的那样工作。但是文档中没有提到如何返回值。文档中没有任何函数返回值,因此我不明白如何执行此操作。

以文档为例:

import click

@click.command()
@click.option('--count', default=3, help='Number of greetings.')

def hello(count):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello')

if __name__ == '__main__':
    hello()

我想做什么:

import click

@click.command()
@click.option('--count', default=3, help='Number of greetings.')

def hello(count):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello')
    return "hello hi"

if __name__ == '__main__':
    print(hello())

“hello hi”未在控制台上作为输出返回。有人能告诉我如何实现这个目标吗?

4 个答案:

答案 0 :(得分:6)

不幸的是,你要做的事情没有意义。命令行程序可以有退出代码,但这只是一个小整数;它们不能返回文本或任意Python对象。

这些整数意味着什么是准标准;简单版本为0表示成功,1表示大多数错误,2表示无效命令行参数。 click正在尝试将您的函数变成一个好的命令行公民,因此当您退出函数时,它会调用sys.exit并使用相应的数字(如果您return则为0;如果您{1} raise,如果它无法解析你的参数,则为2。)

所以,无论你return没有任何效果,无论你试图用顶层的返回值做什么都不会运行。

当需要“返回”文本时,通常执行的程序是将其打印到标准输出,这正是click.echo的用途。

答案 1 :(得分:0)

你必须告诉click使用click.echo()打印到stdout。这是一个使用您问题中的代码的工作示例(不像其他人提到的那样关心退出代码):

import click


@click.command()
@click.option('--count', default=3, help='Number of greetings.')
def hello(count):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello')
    return click.echo("hello hi")

if __name__ == '__main__':
    hello()

答案 2 :(得分:0)

在查看 click 的源代码/参考后,我偶然发现了 BaseCommandmain() 方法,它采用参数 standalone_mode,如果禁用(它是 True),则允许您返回值默认情况下)。希望这对未来的人有所帮助。

设置代码:

import sys
import click

@click.group(invoke_without_command=True)
@click.option('--option1')
@click.argument('arg1')
def main(option1, arg1):
    class SpecialObject():
        def __init__(self, option, arg):
            self.option = option
            self.arg = arg
        def __repr__(self):
            return str(self.option)+str(self.arg)

    return SpecialObject(option1, arg1)

@main.command()
def subcmd():
    return [4,5,6]

测试代码:

if __name__ == "__main__":
    commands = (
        ["--help"], 
        ["arg_val",],
        ["--option1","option1_val","arg1_val"],
        ["arg_val","subcmd"],
        ["arg_val","subcmd", "--help",], 
    )
    print(f'Click Version: {click.__version__}')
    print(f'Python Version: {sys.version}')
    for cmd in commands:
        print('-----------')
        print(f'Starting cmd:{cmd}')
        ret_val = main.main(cmd, standalone_mode=False)
        print(f"Returned: {type(ret_val)}, {ret_val}\n"

输出:

$ python __main__.py
Click Version: 7.1.2
Python Version: 3.9.1 (default, Dec 11 2020, 09:29:25) [MSC v.1916 64 bit (AMD64)]
-----------
Starting cmd:['--help']
Usage: __main__.py [OPTIONS] ARG1 COMMAND [ARGS]...

Options:
  --option1 TEXT
  --help          Show this message and exit.

Commands:
  subcmd
Returned: <class 'int'>, 0

-----------
Starting cmd:['arg_val']
Returned: <class '__main__.main.<locals>.SpecialObject'>, Nonearg_val

-----------
Starting cmd:['--option1', 'option1_val', 'arg1_val']
Returned: <class '__main__.main.<locals>.SpecialObject'>, option1_valarg1_val

-----------
Starting cmd:['arg_val', 'subcmd']
Returned: <class 'list'>, [4, 5, 6]

-----------
Starting cmd:['arg_val', 'subcmd', '--help']
Usage: __main__.py subcmd [OPTIONS]

Options:
  --help  Show this message and exit.
Returned: <class 'int'>, 0

答案 3 :(得分:-3)

显然,这个click包使您的hello()函数永远不会返回。所以印刷品永远不会发生。如果我是你,我不会使用这个不直观的包,而是使用argparse,这在Python中的命令行处理方面很棒(在我看来,这是任何一种语言中最好的一种)。

以下是使用argparse的代码的工作版本。它与Python(任何版本2.7或更高版本)开箱即用,并且很容易理解。

def hello(count):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        print('Hello')
    return "hello hi"

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--count', default=3, type=int, help='Number of greetings.')
    args = parser.parse_args()

    print(hello(args.count))