我正在尝试使用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”未在控制台上作为输出返回。有人能告诉我如何实现这个目标吗?
答案 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 的源代码/参考后,我偶然发现了 BaseCommand 的 main()
方法,它采用参数 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))