使用python click 库创建命令行工具时,是否可以向函数传递未知数量的参数?我正在考虑类似于 *args 命令的东西。
我正在尝试为catkin构建一个包装器,并希望使用click来获取它附带的所有不错的实用程序。在使用指定的命令调用catkin之前,该应用程序应该执行一些任务,例如更改为工作区的根目录。例如catkin build编译代码。问题是,我不想显式声明可以传递给catkin的每个可能的编译标志,而是只想查找实际命令并将所有参数直接传递给catkin。
到目前为止,我发现可以使用选项定义最后一个参数,该选项nargs=-1将收集该变量中的所有后续参数。通过这种方式,您可以收集例如几个文件名。这几乎就是我正在寻找的,除了它不会采用以破折号开头的标志-。它将来自一个错误说Error: no such option: -a
#!/usr/bin/python
import click
import subprocess
@click.command()
@click.argument('action', type=click.STRING)
@click.option('--debug', is_flag=True, help='Build in debug mode.')
@click.argument('catkin_args', nargs=-1, type=click.STRING)
def main(action, debug, catkin_args):
""" A wrapper for catkin """
# Do something here ...
if debug:
# Do some more special things...
subprocess.call(["catkin"] + catkin_args)
Run Code Online (Sandbox Code Playgroud)
我已经使用了argparse一段时间了,但我正在过渡到使用click.
我如何知道click应该使用类似选项的参数,而不必--在该参数之前传递命令行?
例子:
@cli.group()
@click.argument('script')
@click.argument('args', nargs=-1)
def run(script, args):
# ...
Run Code Online (Sandbox Code Playgroud)
我希望能够将其运行为:
mycli run foo.py arg1 --arg2
Run Code Online (Sandbox Code Playgroud)
并--arg2在args列表中,而不必使用命令行:
mycli run -- foo.py arg1 --arg2
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用基于 Click 的 Flask CLI 基础设施来实现命令行应用程序。它的界面应该像这样工作:
app.py -c config.cfg cmd_a
app.py -c config.cfg cmd_b
Run Code Online (Sandbox Code Playgroud)
我有以下代码:
@click.group
@click.option('-c', 'config')
@click.pass_context
def cli(ctx, config):
ctx.obj = ObjA(config)
ctx.obj = ObjB(config) # Just for illustration
@cli.command()
@click.pass_context()
def cmd_a(ctx):
ctx.find_object(ObjA)
@cli.command()
@cli.pass_context()
def cmd_b(ctx):
ctx.find_object(ObjB)
cli()
Run Code Online (Sandbox Code Playgroud)
问题是,我需要根据标志创建两个不同的对象,-c并使它们都可供底层命令使用,这似乎是不可能的。有什么解决方法吗?
我知道我可以使用metaContext 对象的属性,但这意味着要编写大量样板文件。
我正在使用Click构建 CLI 界面。Click 提供了提示的动态默认值,这很棒。此外,此示例还提供了有关如何使用自定义点击类实现动态默认值的一些见解,从而在评估默认值时提供更灵活的选项。
我现在想做的是根据另一个提供的点击选项设置动态默认值,例如
python mymodule --param1 something --param2 somethingelse
Run Code Online (Sandbox Code Playgroud)
现在,如果param2为空,我想尝试根据提供的param1输入获取动态默认值,例如:
@click.command()
@click.option('--param1', prompt=True)
@click.option('--param2', prompt=True, default=lambda: myfunct(param1))
def cmd(param1, param2):
pass
myfunct(param1:str=None):
param2 = None
#get param2 based on param1 input
return param2
Run Code Online (Sandbox Code Playgroud)
关于什么是完成这项工作的最佳方法有什么想法吗?是否保证param1之前进行评估(并提示)param2?
该点击包允许从使用所述列表中选择一个值的范围click.Choice方法。
在我的情况下,这些值是相对较长的字符串,因此使用:
choice_names = [u'Vulnerable BMC (IPMI)', u'IoT Vulnerability', u'SMBv1', u'BadHTTPStatus', u'Compromised']
@click.option('--category', prompt='\nPlease enter the category of incident.\n\n -- Options:\n{}\n\n'.format(
format_choices(choice_names)), type=click.Choice(choice_names))
Run Code Online (Sandbox Code Playgroud)
将列出的值如下:
-> Vulnerable BMC (IPMI)
-> IoT Vulnerability
-> SMBv1
-> BadHTTPStatus
-> Compromised
Run Code Online (Sandbox Code Playgroud)
这需要用户输入完整的字符串,不方便。Click 是否提供仅使用数字标识符来选择值的功能?因此,上述选项可以列为:
-> Vulnerable BMC (IPMI) [1]
-> IoT Vulnerability [2]
-> SMBv1 [3]
-> BadHTTPStatus [4]
-> Compromised [5]
Run Code Online (Sandbox Code Playgroud)
并且要选择第一个选项,用户需要输入1。这可以通过定义自定义验证函数来实现,但我找不到 Click 提供的任何现有功能。
我有一个使用最新点击包的 Python 3.6 脚本。我有很多命令,所以我想移动一些到单独的模块。例如
main.py: root, with commands A and B as children
mylib1.py: commands C and D
mylib2.py: commands E and F
Run Code Online (Sandbox Code Playgroud)
然后在main我想“导入” C 到 F 这样 main 似乎有所有 6 个命令,即所有 6 个都是 root 的孩子。
蛮力是很多维护:
# mylib1.py
@click.command()
def cmd1():
...
...
@click.command()
def cmdN():
...
# main.py
import click
from mylib1 import cmd1, cmd2, ... cmdN
@click.group()
def main(): pass
@main.command()
def main_cmd1(): pass
main.add_command(cmd1)
...
main.add_command(cmdN)
Run Code Online (Sandbox Code Playgroud)
少一点维护(无需管理导入):
# mylib1.py
def add_commands(group):
group.add_command(cmd1)
...
group.add_command(cmdN) …Run Code Online (Sandbox Code Playgroud) 我创建了一个 Click 命令,它将文件从源复制到目标
该命令接受 3 个参数:
1 - 文件来源
2 - 文件的目的地
3 - 传输模式(本地,ftp)
import click
@click.group()
def cli():
pass
@cli.command()
@click.argument('source')
@click.argument('destination')
@click.option('--mode', required = True)
def copy(source, destination, mode):
print("copying files from " + source + " to " + destination + "using " + mode + " mode")
if __name__ == '__main__':
cli()
Run Code Online (Sandbox Code Playgroud)
当我使用这个调用脚本时: command.py copy "C:/" "D:/" --mode=network
我得到以下输出: copying files from C:/ to D:/using network mode
如您所见,我将网络指定为模式,但我只需要两个选项:本地或 ftp
那么如何使用 Click 来设置选项的允许值呢?
假设我想创建一个看起来像这样的 CLI
cliName user create
cliName user update
Run Code Online (Sandbox Code Playgroud)
我该怎么做?
我试过做这样的事情 -
@click.group()
def user():
print("USER")
pass
@user.command()
def create():
click.echo("create user called")
Run Code Online (Sandbox Code Playgroud)
当我运行时cliName user create,打印语句不运行。什么都跑。
假设我有一个包含参数和选项的字符串列表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)
Run Code Online (Sandbox Code Playgroud)
在这里,argparse解析了一个提供的可迭代字符串。也可以click用来解析提供的字符串可迭代吗?
我已经搜索了 API 文档,click似乎parse_args在一*Command组类中有一个函数,但在文档中没有看到关于我如何做到这一点的任何内容。我已经尝试过实例化BaseCommand,Command但不确定如何parse_args在没有正确上下文的情况下工作。
对于更广泛的上下文,这个问题是构建了一个启动器应用程序的结果,最终用户将其用作启动他们自己的应用程序的脚手架。在这里,启动器使用了许多参数,点击装饰器可以完美地使用这些参数。可以按照此处的文档中所示处理未知参数。然后,该启动器使用这些未解析的参数调用提供可调用的最终用户。Click 将未解析的参数作为字符串元组。在这种情况下,最终用户如何能够使用 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 …Run Code Online (Sandbox Code Playgroud) 我正在使用 Python 和 Click 库构建 CLI 应用程序。
我如何实现以下用例:
首先,我只希望子命令后跟一个参数,不需要任何选项:
$ myapp subcommand argument
Run Code Online (Sandbox Code Playgroud)
这是直截了当的。
但是我如何编写代码,如果设置了参数2,还需要一些选项?
$ myapp subcommand argument2 -o1 abc -o2 def
Run Code Online (Sandbox Code Playgroud)
例如:
不需要任何选项:
$ ./myapp.py install basic
Run Code Online (Sandbox Code Playgroud)
需要以下选项:
$ ./myapp.py install custom -o1 abc -o2 def
Run Code Online (Sandbox Code Playgroud)
此外,我不知道如何选择参数,这意味着用户必须在“基本”或“自定义”之间进行选择。如果他选择“自定义”,他需要添加一些选项。