说我有一个包含参数和选项的字符串列表,使用argparse
,我可以使用parse_args
函数将此列表解析为一个对象,如下所示:
import argparse
extra_params = [‘—sum’, ‘7’, ‘-1’, ‘42’]
parser=argparse.ArgumentParser(description=“argparse docs example”)
parser.add_argument(‘integers’, metavar=‘N’, type=int, nargs=‘+’,
help=‘an integer for the accumulator’)
parser.add_argument(‘—sum’, dest=‘accumulate’, action=‘store_const’,
const=sum, default=max,
help=‘sum the integers (default: find the max)’)
parsed_object=parser.parse_args(extra_params)
[这里,argparse
已解析了提供的字符串可迭代。可以使用click
来解析提供的可迭代字符串吗?
我在API文档中搜索了click
,似乎在parse_args
组类中有一个*Command
函数,但是在文档中看不到我该怎么做。我尝试实例化BaseCommand
和Command
,但不确定如何在没有正确上下文的情况下使parse_args
工作。
从更广泛的意义上讲,这个问题是由于构建了启动器应用程序而导致的,最终用户将其用作启动自己的应用程序的支架。在这里,启动器使用许多参数,单击装饰器可以针对这些参数完美地工作。可以按照文档here中所示处理未知参数。然后,此启动程序将调用可与这些未解析的参数一起调用的最终用户。单击将未解析的参数保留为字符串元组。在这种情况下,最终用户将如何使用Click来解析他们感兴趣的参数?以下是说明问题的代码段:
import click
from typing import Tuple
@click.command(name="TestLauncher", context_settings={
"ignore_unknown_options": True
})
@click.option('--uri', '-u',
help="URI for the server")
@click.argument('unprocessed_args', nargs=-1,
type=click.UNPROCESSED)
def main(uri: str, unprocessed_args: Tuple[str, ...]) -> None:
print(f"Was passed a URI of {uri}")
print(f"Additional args are {unprocessed_args}")
child_function(unprocessed_args)
def child_function(unprocessed_args: Tuple[str, ...]) -> None:
# How do I get Click to parse the provided args for me?
pass
if __name__ == "__main__":
# pylint: disable=no-value-for-parameter, unexpected-keyword-arg
main()
从命令行运行此:
python3 so_test.py --uri test.com --prog-arg 10
Was passed a URI of test.com
Additional args are ('--prog-arg', '10')
尝试这样的事情:
import click
@click.command()
@click.option('--count', default=1, help='number of greetings')
@click.option('--test', default='test_was_not_provided', help='test option')
@click.argument('name')
def hello(*args, **kwargs):
click.echo(f"Hello World! {kwargs['name']} {kwargs['count']}")
if __name__ == '__main__':
hello()
运行类似:python main.py haha --test this_is_a_test --count=40
查看评论和随后进行的编辑,使我认为仅将click装饰器应用于子功能可能会起作用。确实确实如此,但我并不完全知道为什么。
import click
from typing import Tuple
@click.command(name="TestLauncher", context_settings={
"ignore_unknown_options": True
})
@click.option('--uri', '-u',
help="URI for the server")
@click.argument('unprocessed_args', nargs=-1,
type=click.UNPROCESSED)
def main(uri: str, unprocessed_args: Tuple[str, ...]) -> None:
print(f"Was passed a URI of {uri}")
print(f"Additional args are {unprocessed_args}")
child_function(unprocessed_args)
@click.command()
@click.option('--prog-arg')
def child_function(prog_arg: str) -> None:
# How do I get Click to parse the provided args for me?
print(f"Child function passed: {prog_arg}")
if __name__ == "__main__":
# pylint: disable=no-value-for-parameter, unexpected-keyword-arg
main()
python3 so_test.py --uri test.com --prog-arg 10
Was passed a URI of test.com
Additional args are ('--prog-arg', '10')
Child function passed: 10
由于调用函数对子函数的参数一无所知,您可以尝试以下操作:
@click.command(name="TestLauncher", context_settings={
"ignore_unknown_options": True
})
@click.option('--uri', '-u',
help="URI for the server")
@click.argument('unprocessed_args', nargs=-1,
type=click.UNPROCESSED)
def main(uri: str, unprocessed_args: Tuple[str, ...]) -> None:
print(f"Was passed a URI of {uri}")
print(f"Additional args are {unprocessed_args}")
unprocessed_args = dict([(unprocessed_args[i].replace('--', '').replace('-', '_'), unprocessed_args[i+1]) for i in range(0, len(unprocessed_args), 2)])
click.get_current_context().invoke(child_function, **unprocessed_args)
@click.command(context_settings={"ignore_unknown_options": True})
@click.option('-p', '--prog-arg')
def child_function(prog_arg: str, **kwargs) -> None:
# How do I get Click to parse the provided args for me?
print(f"Child function passed: {prog_arg}")
# all remaining unknown options are in **kwargs
if __name__ == "__main__":
# pylint: disable=no-value-for-parameter, unexpected-keyword-arg
main()
但是,请注意:
unprocessed_args = dict([(unprocessed_args[i].replace('--', '').replace('-', '_'), unprocessed_args[i+1]) for i in range(0, len(unprocessed_args), 2)])
这假设每个选项只能有一个值。另一种选择是通过传递如下所示的选项来调用脚本,在=
上分割字符串,并进行您认为必要的任何预格式化。
--prog-arg=<Your-desired-values>