我正在尝试使用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"不会作为控制台上的输出返回。有人能告诉我如何做到这一点吗?
不幸的是,您试图做的事情没有意义。命令行程序可以有退出代码,但这只是一个小整数;它们不能返回文本或任意Python对象。
这些整数的含义有一个准标准;简单版本为0表示成功,1表示大多数错误,2表示无效的命令行参数。click
试图使您的函数成为一个好的命令行公民,因此当您退出函数时,它会用适当的数字调用sys.exit
(如果您是return
,则为0;如果您是raise
,则为1;如果它未能解析您的参数,则为2)。
因此,无论您使用return
做什么都没有效果,无论您尝试使用顶级返回值做什么都不会运行。
当程序需要"返回"文本时,通常会将其打印到标准输出,这正是click.echo
的作用。
默认情况下,单击会将程序转换为命令行程序,即执行click
命令并返回代码退出。因此,您的程序执行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
Hello
Hello
您可以通过传递参数standalone_mode=False
(单击API命令)来更改此行为:
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(standalone_mode=False))
它打印:
Hello
Hello
Hello
hello hi
在浏览了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
您必须告诉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()
请在此处查看点击文档,也可以在此处查看此答案
# Main Runtime call at bottom of code
hello(standalone_mode=False)
# or e.g
main(standalone_mode=False)
显然,这个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))