gpt4 book ai didi

python - 从代码中调用点击命令

转载 作者:行者123 更新时间:2023-12-04 08:20:49 26 4
gpt4 key购买 nike

我有一个使用click包装为命令的函数。所以看起来像这样:

@click.command()
@click.option('-w', '--width', type=int, help="Some helping message", default=0)
[... some other options ...]
def app(width, [... some other option arguments...]):
[... function code...]

我对此功能有不同的用例。有时,可以通过命令行调用它,但是有时候我也想直接调用该函数
from file_name import app
width = 45
app(45, [... other arguments ...])

我们该怎么做?我们如何使用click调用已包装为命令的函数?我找到了这个 related post,但是我不清楚如何使它适应我的情况(即,从头开始构建Context类,并在click命令功能之外使用它)。

编辑:我应该提到:我不能(轻松地)修改包含要调用的函数的程序包。因此,我正在寻找的解决方案是如何从调用者这方面进行处理。

最佳答案

您可以通过从参数重建命令行来从常规代码调用click命令功能。使用您的示例,它看起来可能像这样:

call_click_command(app, width, [... other arguments ...])

代码:
def call_click_command(cmd, *args, **kwargs):
""" Wrapper to call a click command

:param cmd: click cli command function to call
:param args: arguments to pass to the function
:param kwargs: keywrod arguments to pass to the function
:return: None
"""

# Get positional arguments from args
arg_values = {c.name: a for a, c in zip(args, cmd.params)}
args_needed = {c.name: c for c in cmd.params
if c.name not in arg_values}

# build and check opts list from kwargs
opts = {a.name: a for a in cmd.params if isinstance(a, click.Option)}
for name in kwargs:
if name in opts:
arg_values[name] = kwargs[name]
else:
if name in args_needed:
arg_values[name] = kwargs[name]
del args_needed[name]
else:
raise click.BadParameter(
"Unknown keyword argument '{}'".format(name))


# check positional arguments list
for arg in (a for a in cmd.params if isinstance(a, click.Argument)):
if arg.name not in arg_values:
raise click.BadParameter("Missing required positional"
"parameter '{}'".format(arg.name))

# build parameter lists
opts_list = sum(
[[o.opts[0], str(arg_values[n])] for n, o in opts.items()], [])
args_list = [str(v) for n, v in arg_values.items() if n not in opts]

# call the command
cmd(opts_list + args_list)

这是如何运作的?

之所以行之有效,是因为click是一个设计良好的OO框架。可以对 @click.Command对象进行自检,以确定它需要什么参数。然后可以构造一个命令行,该命令行看起来像单击所期望的命令行。

测试代码:
import click

@click.command()
@click.option('-w', '--width', type=int, default=0)
@click.option('--option2')
@click.argument('argument')
def app(width, option2, argument):
click.echo("params: {} {} {}".format(width, option2, argument))
assert width == 3
assert option2 == '4'
assert argument == 'arg'


width = 3
option2 = 4
argument = 'arg'

if __name__ == "__main__":
commands = (
(width, option2, argument, {}),
(width, option2, dict(argument=argument)),
(width, dict(option2=option2, argument=argument)),
(dict(width=width, option2=option2, argument=argument),),
)

import sys, time

time.sleep(1)
print('Click Version: {}'.format(click.__version__))
print('Python Version: {}'.format(sys.version))
for cmd in commands:
try:
time.sleep(0.1)
print('-----------')
print('> {}'.format(cmd))
time.sleep(0.1)
call_click_command(app, *cmd[:-1], **cmd[-1])

except BaseException as exc:
if str(exc) != '0' and \
not isinstance(exc, (click.ClickException, SystemExit)):
raise

测试结果:
Click Version: 6.7
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> (3, 4, 'arg', {})
params: 3 4 arg
-----------
> (3, 4, {'argument': 'arg'})
params: 3 4 arg
-----------
> (3, {'option2': 4, 'argument': 'arg'})
params: 3 4 arg
-----------
> ({'width': 3, 'option2': 4, 'argument': 'arg'},)
params: 3 4 arg

关于python - 从代码中调用点击命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48619517/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com