命令行接口的声明性解析器
cliglue的Python项目详细描述
cli glue-用于cli的胶水
cliglue
是python中命令行接口的声明性解析器。
它是cli shell参数和正在调用的函数之间的绑定粘合剂。
cliglue
在运行控制台应用程序时解析并验证用户提供的命令行参数。
然后根据声明的命令行接口规则,自动触发匹配的操作,注入所有需要的参数。
您不需要每次都为绑定和解析参数编写"粘合"代码。
因此,它使编写控制台应用程序更快、更简单。
功能
- 自动生成的帮助和用法(
--help
) - 外壳自动完成(获取有关点击
选项卡
的最相关提示) - 多级子命令(例如
git remote add…
语法) - 命名参数:同时支持
--名称值
和--名称=值
,多个参数出现 - 标志:支持短(
-f
)和长(--force
),组合短标志(-tulpn
),多个标志出现(-vvv
) - 位置参数(例如,
git push<;origin>;
) - 键值字典(例如
--配置键值
) - 调用匹配的操作函数&injecting parameters
- 自定义类型验证器/分析器
- 自定义自动完成程序(可能值的提供程序)
- 处理语法错误,第仪表验证
- 键入的值(int、time、date、file等)
- 默认情况下启用标准选项(
--help
,--version
) - 声明式cli生成器
快速启动
让我们使用cliglue创建简单的命令行应用程序。 假设我们已经有了如下函数:
defsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)
我们需要一个"胶水",它与cli(命令行界面)绑定。
我们希望它以用户提供给终端外壳的不同参数运行:
/hello.py world--reverse--repeat=1
。
我们刚刚确定了一个位置参数、一个标志和一个数值参数。
因此,我们的cli定义可以使用cliglue声明
CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),)
总而言之,我们用命令行界面绑定了函数:
你好。py:
#!/usr/bin/env python3fromcliglueimportCliBuilder,argument,flag,parameterdefsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),).run()
让我们追踪这里发生的事情:
clibuilder
为整个应用程序生成cli树。'hello-app'
是要在帮助输出中显示的应用程序的名称。run=say_hello
设置应用程序的默认操作。现在一个函数say_hello
被绑定为一个主操作,如果没有匹配的其他操作,它将被调用。.has(…)
允许在该生成器中嵌入其他规则。返回clibuilder本身。参数('name')
声明位置参数。从现在起,第一个cli参数(在二进制名称之后)将被识别为name
变量。flag('reverse')
将--reverse
关键字绑定到名为reverse
的标志。以便以后使用。参数('repeat',type=int,default=1)
将--repeat
关键字绑定到名为repeat
的参数,该参数的类型为int
,其默认值为1
- 最后,调用
.run()
完成所有的魔术。 它获取系统参数列表,开始处理它们并调用相关操作。
帮助/用法
clibuilder
默认情况下添加了一些基本选项,如--help
或--version
。
因此,您可以使用--help
标志运行应用程序来检查使用情况:
foo@bar:~$ ./hello.py --help hello-appUsage: ./hello.py [OPTIONS] NAMEOptions: -h, --help [SUCOMMANDS...] - Display this help and exit --reverse --repeat REPEAT
请注意,已经显示了一些规则,这些规则是以前声明的:
- 位置参数
名称
:/hello.py[选项]名称
- 标志
倒车
:--倒车
- 参数
重复
:--重复
注入参数
现在,当我们使用提供的一个参数执行应用程序时,会得到:
foo@bar:~$ ./hello.py world Hello world.
注意world
已被识别为name
参数。
我们将say\u hello
绑定为默认操作,因此它已使用特定参数调用:
say_hello(name='world',reverse=False,repeat=1)
- 位置参数
name
被分配了一个'world'
值。 - 未给出标志
reverse
,因此默认情况下为false
。 - 参数
repeat
也未给定,因此将其设置为默认值1
让我们显式地提供所有参数,然后得到:
foo@bar:~$ ./hello.py --reverse world --repeat 2Hello dlrow.Hello dlrow.
或者我们可以用不同的方式来做同样的事情:
foo@bar:~$ ./hello.py world --repeat=2 --reverse Hello dlrow.Hello dlrow.
当您正在为操作编写函数,并且需要访问某些变量(标志、参数、参数等)时,
只需在函数中添加一个与所需变量同名的参数。
然后,通过cliglue
它是如何工作的?
- 你定义了一切声明树中程序所需的cli规则。
- 在shell中运行程序时,用户提供命令行参数。
cliglue
解析并验证所有参数、标志、子命令、位置参数等,并在内部存储它们。cliglue
找到最相关的操作(从最具体的开始)并调用它。- 调用函数时,
cliglue
根据先前定义和分析的值注入它所需的所有参数。
您只需将关键字绑定到规则,然后cliglue
将为您处理其余的所有内容。
cliglue
vsargparse
既然我们已经有了pythonargparse
,为什么要使用cliglue
?以下是cliglue的一些主观优势:
- 一个地方的cli逻辑声明方式,
- 开箱即用的自动完成功能,
- 构建多级子命令的更简单方法,
- 自动操作绑定和注入参数,无需手动将参数传递给函数,
- 与应用程序逻辑分离的cli逻辑,
- 更简单简洁的cli构建-在读取代码时,更容易区分它们之间的特定cli规则(即位置参数、参数或子命令的标志),
- 作为清晰文档的cli定义代码。
从argparse
迁移到cliglue
基本客户端
argparse:
importargparseparser=argparse.ArgumentParser(description='Program description')[herecometherules...]args=parser.parse_args()do_something(args)
剪贴画:
defsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)0
标志
argparse:
defsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)1
剪贴画:
defsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)2
位置参数
argparse:
defsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)3
剪贴画:
defsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)4
子命令
argparse:
defsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)5
剪贴画:
defsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)6
将值传输到函数
argparse:
defsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)7
剪贴画:
defsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)8
安装
第1步。先决条件
- python 3.6(或更新版本)
关于Debian 10(Buster)
defsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)9
在Debian 9上(拉伸)
不幸的是,Debian Stretch发行版的存储库中没有Python3.6+,但是可以从源代码编译它:
CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),)0 在ubuntu 18上
CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),)1
在CentOS 7上
CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),)
2
在软呢帽上
CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),)
3
第2步。使用pip安装软件包
CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),)3
第2步。使用pip安装软件包
从使用pip:
的pypi存储库安装包CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),)4
或者使用显式python版本:
CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),)5
以开发模式安装软件包
您可以在开发模式下安装软件包,以便对自己的软件包进行任何更改:
CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),)6
测试
运行测试:
CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),)7
clibuilder
clibuilder
是cliglue
包的一个主要类,它允许构建cli定义。
它是一个命令行接口规范的构建器。
之后,您可以调用.run()
方法来解析提供的参数并调用特定的操作。
空clibuilder默认情况下启用了标准选项:
--help
-显示用法和帮助--版本
-显示应用程序版本号(如果已定义)
第1步。创建clibuilder
在此步骤中,您可以创建新的clibuilder
并为其设置自定义配置。
构造函数如下:
CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),)8
名称
-为其生成cli的应用程序的名称
版本
-应用程序版本(显示在帮助/版本输出中)
帮助
-应用程序的简短说明
运行
-函数的引用,该函数应该是空参数列表的默认操作
使用默认值-是否应添加默认规则和操作。
默认选项为:
-h,--帮助:显示帮助,
--版本:显示版本,
--bash install app-name:安装应用程序在bash中自动完成,
--bash autocomplete[命令行…]:生成由bash处理的自动完成的建议的内部操作
用法错误
-语法错误时应显示用法输出
reraise_error
-不应捕获语法错误,而应重新引发语法错误。
启用此选项将导致堆栈跟踪被淹没到用户。
hide_internal
-内部选项(--bash install
,--bash autocomplete
)应在帮助输出中隐藏。
第2步。声明cli规则
下一步是使用.has()
方法为clibuilder
声明cli规则
has(*subrules:clirule)->;'clibuilder'
方法在其参数中接收一个cli规则,并返回clibuilder
自身以进行进一步的构建。
它用于引入下一级的子规则。
可用规则如下:
- 子命令
- 标志
- 参数
- 参数
- 参数
- 默认操作
- 主选项
示例:
CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),)9
第3步。通过解析器运行cli参数
最后一步是调用clibuilder上的.run()
。
它解析传递给应用程序的所有cli参数。
然后调用之前定义的触发动作。
如果操作需要一些参数,则将根据解析的参数注入这些参数。
运行空生成器:
#!/usr/bin/env python3fromcliglueimportCliBuilder,argument,flag,parameterdefsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),).run()0
只打印标准帮助输出,因为如果没有提供参数,它是空生成器的默认操作。
子命令
命令可以用嵌套的子命令形成多级树。 子命令语法是众所周知的,例如:
Git远程重命名…
码头集装箱LS
nmcli设备WiFi列表
IP地址显示
子命令将cli分成许多嵌套的cli级别,形成一个树。 它们决定将解析器指向何处,解析器寻找要调用的最相关的操作,并决定哪些规则处于活动状态。
子命令创建子解析器的嵌套级别,这些子解析器不仅可能具有不同的操作,而且还包含不同的cli规则,例如命名参数、标志或其他子命令,这些子命令仅在启用父命令时才启用。 子命令可以有更多的子规则,只有当相应的子命令处于活动状态时才会激活这些子规则。 所以子命令只是一个缩小上下文范围的关键字。
子命令规范
要创建子命令规则规范,请使用:
#!/usr/bin/env python3fromcliglueimportCliBuilder,argument,flag,parameterdefsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),).run()1
关键字
-它们中的任何一个都可能触发子命令的关键字参数
运行
-匹配子命令时要调用的可选操作
帮助
-帮助输出中显示的参数说明
嵌套子命令
使用子命令,可以嵌套其他cli规则。 只有当相应的子命令处于活动状态时,它们才会处于活动状态。
子规则可以使用嵌套。has(*subrules:clirule)
方法。
它返回自身以进行进一步的构建,因此可以像clibuilder
:
#!/usr/bin/env python3fromcliglueimportCliBuilder,argument,flag,parameterdefsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),).run()2
这样,上面的格式化代码就构成了一个清晰可见的可视树。
子命令示例:sub commands.py
#!/usr/bin/env python3fromcliglueimportCliBuilder,argument,flag,parameterdefsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),).run()3
用法很自我描述:
#!/usr/bin/env python3fromcliglueimportCliBuilder,argument,flag,parameterdefsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),).run()4
有关更详细的用例,请参见子命令测试。
标志
flag是一个由单个关键字切换的布尔参数。
支持短格式(-f
)和长格式(--force
)。
要创建标志规则规范,请使用:
#!/usr/bin/env python3fromcliglueimportCliBuilder,argument,flag,parameterdefsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),).run()5
关键字
是参数(一个或多个),它们中的任何一个在发生时启用标志。
标志值-f
或--flag
,
以及按名称:f
或标志
,也将计算为-f
或--标志
。
单字符标志将得到单连字符前缀(-f
),
较长的标志名称将得到双连字符前缀(--flag
)。
帮助
是帮助输出中显示的标志的说明
multiple
-是否允许多次出现标志。
然后标志具有int类型并存储其出现次数
示例:
#!/usr/bin/env python3fromcliglueimportCliBuilder,argument,flag,parameterdefsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),).run()6
用法:
#!/usr/bin/env python3fromcliglueimportCliBuilder,argument,flag,parameterdefsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),).run()7
组合用短标志
许多短标志可以组合在一个参数中。您只需键入-tulpn
,而不是-t-u-l-p-n
。
多次出现标记
标志也支持多次出现。当multiple
设置为true
时,标志值表示设置了多少次。然后,值类型是int
,而不是bool
#!/usr/bin/env python3fromcliglueimportCliBuilder,argument,flag,parameterdefsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),).run()8
那么-vvv
应该返回3
有关更详细的用例,请参见标志测试。
命名参数
参数是一个命名值,它将按其名称注入已触发的操作。
参数值的设置支持两种方式:
--参数名值
或--参数名=值
命名参数可以出现在cli参数列表中的任何位置:开头或结尾,甚至在位置参数之前。 只要它们作为命名参数匹配,就不会被识别为位置参数。
这些参数以后可以由其名称或关键字引用
(小写格式,不带连字符前缀,带下划线而不是破折号,
例如,--参数名
将被注入为参数名
)
要创建参数规则规范,请使用:
#!/usr/bin/env python3fromcliglueimportCliBuilder,argument,flag,parameterdefsay_hello(name:str,reverse:bool,repeat:int):ifreverse:name=name[::-1]print(f'Hello {name}.'*repeat)CliBuilder('hello-app',run=say_hello).has(argument('name'),flag('reverse'),parameter('repeat',type=int,default=1),).run()9
关键字
与参数匹配的关键字参数。
参数关键字可以使用直接格式传递:-p
或--param
,
以及按名称:p
或param
,将计算为-p
或--param
。
单字符参数将得到单连字符前缀(-p
),
较长的参数名将得到双连字符前缀(--param
)
name
是显式参数名(当它与任何关键字不同时,可以使用)
帮助
是帮助输出中显示的参数的说明
必需
指示是否需要参数。
如果需要,但没有给出,则会引发语法错误。
默认值
是参数的默认值,如果没有给定(并且不是必需的)。
type
是一种参数值类型(例如str、int、float)。
这里也可以提供对解析器函数的引用。
然后通过将字符串参数值传递给该函数来计算参数值。
选项
是参数值可用选项的显式列表
或引用将被调用以检索此类可能值列表的函数
严格的选项
-是否应根据可用选项验证给定参数
multiple
-参数是否允许多次出现。
然后参数具有列表类型并存储值列表
基本参数示例:
foo@bar:~$ ./hello.py --help hello-appUsage: ./hello.py [OPTIONS] NAMEOptions: -h, --help [SUCOMMANDS...] - Display this help and exit --reverse --repeat REPEAT0
foo@bar:~$ ./hello.py --help hello-appUsage: ./hello.py [OPTIONS] NAMEOptions: -h, --help [SUCOMMANDS...] - Display this help and exit --reverse --repeat REPEAT1
出现多个参数
参数也支持多次出现。
当multiple
设置为true
时,参数值表示值的列表,并且可以附加多个时间。
然后,值类型是列表
foo@bar:~$ ./hello.py --help hello-appUsage: ./hello.py [OPTIONS] NAMEOptions: -h, --help [SUCOMMANDS...] - Display this help and exit --reverse --repeat REPEAT2
foo@bar:~$ ./hello.py --help hello-appUsage: ./hello.py [OPTIONS] NAMEOptions: -h, --help [SUCOMMANDS...] - Display this help and exit --reverse --repeat REPEAT3 < P> SE有关更详细的用例,请参见参数测试。
位置参数
位置参数是一个未命名的参数,只能通过其在命令行参数列表中的顺序来识别。 例如,前两个参数(标志和命名参数除外)可以检测为位置参数,并与相应的变量匹配。
单个位置参数
假设我们有cli语法:git push<;origin>;
git
当然是应用程序的二进制名称,push
是一个子命令,它有两个位置参数:origin
和master
要创建位置参数规则规范,请使用:
foo@bar:~$ ./hello.py --help hello-appUsage: ./hello.py [OPTIONS] NAMEOptions: -h, --help [SUCOMMANDS...] - Display this help and exit --reverse --repeat REPEAT4
名称
-内部参数名称,用于引用参数值
帮助
-帮助输出中显示的参数说明
必需
-是否需要位置参数。
如果需要,但没有给出,则会引发语法错误。
默认值
-参数的默认值,如果未给定(且不是必需的)
type
-参数值的类型(例如str、int、float)
这里也可以提供对解析器函数的引用。
然后通过将字符串参数值传递给该函数来计算参数值。
选项
-参数值可用选项的显式列表
或引用将被调用以检索此类可能值列表的函数。
严格的选项
-是否应根据可用选项验证给定参数
示例:pos args.py
foo@bar:~$ ./hello.py --help hello-appUsage: ./hello.py [OPTIONS] NAMEOptions: -h, --help [SUCOMMANDS...] - Display this help and exit --reverse --repeat REPEAT5
用法:
foo@bar:~$ ./hello.py --help hello-appUsage: ./hello.py [OPTIONS] NAMEOptions: -h, --help [SUCOMMANDS...] - Display this help and exit --reverse --repeat REPEAT6
请参阅作为规范的位置参数测试。
许多位置参数
cliglue
允许匹配所有剩余(尚未匹配)参数。
当使用docker cmd
这样的语法时,它很有用:
docker运行命令ubuntu/bin/bash-c/script.sh
使用该语法,ubuntu-/bin/bash-c/script.sh
之后的所有参数都应该与一个变量匹配。
您可以使用cliglue
使用arguments
。
该规则将强制解析器将所有剩余的参数存储在一个列表变量中(或一个连接的字符串中)。
要创建"多参数"规则规范,请使用:
foo@bar:~$ ./hello.py --help hello-appUsage: ./hello.py [OPTIONS] NAMEOptions: -h, --help [SUCOMMANDS...] - Display this help and exit --reverse --repeat REPEAT7
它允许检索特定数量的cli argumetns或所有剩余的参数。 所有匹配的参数将被提取到参数列表或字符串中(取决于用参数连接的
名称
-内部变量名称,用于引用匹配的参数
类型
-参数值的显式类型(例如str、int、float)
这里也可以提供对解析器函数的引用。
然后通过将字符串参数值传递给该函数来计算参数值
选项
-参数值可用选项的显式列表
或引用将被调用以检索此类可能值列表的函数。
严格的选项
-是否应根据可用选项验证给定参数
count
-要检索的参数的显式数目。
如果未定义,则不验证参数计数。
如果您需要特定数量的参数,可以使用此计数,而不是设置min_count=max_count。
最小计数
-最小参数数。
默认情况下,没有下限(为0)。
最大计数
-最大参数数。
如果未定义,则参数计数没有上限。
用
连接了u-参数的可选字符串连接符。
如果设置好了,妈妈匹配的参数将用该连接符连接到字符串。
如果没有给出,匹配的参数将作为字符串列表传递。
当这个值(字符串或列表)被注入一个函数时,它可以通过指定的名称来访问。
帮助
-帮助输出中显示的参数说明
注意,参数(count=1)
规则与单个参数
规则类似,只是它用一个元素存储列表。
只要设置了计数或
最大计数,就可以使用许多连续的
参数
规则。
示例:many args.py
foo@bar:~$ ./hello.py --help hello-appUsage: ./hello.py [OPTIONS] NAMEOptions: -h, --help [SUCOMMANDS...] - Display this help and exit --reverse --repeat REPEAT8
用法:
foo@bar:~$ ./hello.py --help hello-appUsage: ./hello.py [OPTIONS] NAMEOptions: -h, --help [SUCOMMANDS...] - Display this help and exit --reverse --repeat REPEAT9
有关更详细的用例,请参见许多参数测试。
词典
字典包含键值对。
通过以以下方式传递参数,可以向其添加多个值:
-c name1 value1-c name2 value2
默认情况下,它存储空的python dict。
这些值以后可以通过其显式名称或关键字引用为dict
(小写格式,不带连字符前缀,带下划线而不是破折号,
例如,--配置名
将被注入为配置名
变量名)
要创建字典规则规范,请使用:
foo@bar:~$ ./hello.py world Hello world.0
关键字
-与此词典匹配的关键字参数。
关键字可以使用直接格式传递:-c
或--config
,
以及按名称:c
或config
,将计算为-c
或--config
。
单字符词典将得到单连字符前缀(-c
),
较长的字典名称将得到双连字符前缀(--config
)
名称
-显式内部字典名称(可用于与任何关键字区分)
帮助
-帮助输出中显示的词典说明
键类型
-字典键的类型(例如str、int、float)
这里也可以提供对解析器函数的引用。
然后通过将字符串参数值传递给该函数来计算字典值。
value_type
-字典值的类型(例如str、int、float)
这里也可以提供对解析器函数的引用。
然后通过将字符串参数值传递给该函数来计算字典值。
基本字典示例:
foo@bar:~$ ./hello.py world Hello world.1
foo@bar:~$ ./hello.py world Hello world.2
有关更详细的用例,请参见字典测试。
自动完成
shell自动完成允许在键入命令行时提示有关如何按tab键的最相关提示。
默认情况下,根据声明的子命令和选项,所有已知关键字都将启用由cliglue提供的自动完成功能。
定义可能的选择可能会导入自动完成参数。您可以声明显式可能值列表或在运行时提供此列表的函数。
完成符.py:
foo@bar:~$ ./hello.py world Hello world.3
为了启用自动完成,您需要安装一些bash扩展。幸运的是,cliglue有内置的工具可以做到这一点:
foo@bar:~$ ./hello.py world Hello world.4
现在,我们已经在/usr/bin/
中安装了completers demo
应用程序(指向当前脚本的符号链接)和bash completion脚本。
键入时,我们可以按[tab]
键完成命令。下面是一些完成示例:
foo@bar:~$ ./hello.py world Hello world.5
自定义完成符
您可以为选项
参数提供自定义的自动完成符(可能值的提供者)。
例如,返回可用屏幕列表的函数:
foo@bar:~$ ./hello.py world Hello world.6
您可以使用它来验证和建议参数或位置参数:
foo@bar:~$ ./hello.py world Hello world.7
安装自动完成功能
为了启用自动完成,必须在/etc/bash_completion.d/
中有一个特定的脚本。
使用cliglue
您只需运行:
foo@bar:~$ ./hello.py world Hello world.8
它将安装自动完成脚本并在/usr/bin/
中添加符号链接,
因此,您可以使用sample app
命令而不是/sample-app.py
现在您可以键入示例应用程序
并点击选项卡
查看可能的命令和选项。
如果您键入sample app--he
,它将自动填充唯一可能的选项:--help
有时候,你需要对代码进行一些修改,
但在这些修改之后,您将不需要重新安装自动完成功能。
您只需执行一次,因为自动完成脚本只重定向其查询并运行sample廑app.py
:
foo@bar:~$ ./hello.py world Hello world.9
自动完成是如何工作的?
- 在
bash
中键入命令时,请按选项卡
键。(your-app.py命令[选项卡]
) bash
在/etc/bash_completion.d/
中查找自动完成脚本。 在应用程序上运行--bash install
之后,应该为命令安装一个脚本。 所以当找到这个脚本时,bash会调用它。- 自动完成脚本重定向到应用程序,使用
--bash autocomplete
选项运行它,即脚本运行your-app.py--bash autocomplete"cmd"
,要求它返回最相关的命令建议。 注意,以这种方式,自动完成算法始终以最新版本运行。 默认情况下,app.py
已启用--bash autocomplete
选项,因此它将开始分析cli定义中与当前键入的单词最相关的关键字(cmd
)。- 如果您定义了自定义补全函数,将立即调用它们(如果需要),以便获取最新的建议并对其进行分析。
您的app.py
向bash返回建议列表bash
显示这些结果。 如果只有一个匹配的建议,则自动填充当前键入的单词。
请注意,每次尝试获取匹配参数建议时,您的应用程序都在运行。
自动生成的帮助
cliglue
根据定义的cli规则自动生成帮助和使用情况输出。
假设我们有相当复杂的cli定义:
say_hello(name='world',reverse=False,repeat=1)0
我们可以使用--help
或-h
:
say_hello(name='world',reverse=False,repeat=1)1
子命令帮助
我们还可以仅检查选定子命令的用法:
say_hello(name='world',reverse=False,repeat=1)2
版本检查
使用--version
显示应用程序版本:
say_hello(name='world',reverse=False,repeat=1)3
数据类型
cliglue
支持参数或位置参数的类型化值。
默认情况下,所有值都有字符串类型。
可以通过定义类型
参数来更改。
有两种可能的类型
值:
- 键入名称本身(例如
int
,str
,float
) - 返回值的分析器的引用
在这两种情况下,通过调用
类型(str_value)
计算内部变量值。 当参数值的格式无效时,会产生语法错误。
基本类型(int、float等)
say_hello(name='world',reverse=False,repeat=1)4
say_hello(name='world',reverse=False,repeat=1)5
内置数据类型
cliglue
为某些类型提供了内置的解析器/验证器
文件系统类型
cliglue.types.filesystem.existing_file
验证给定字符串是否是现有的常规文件(而不是目录)。
验证后,该值在内部存储为str
α-αα66
cliglue.types.filesystem.existing_directory
验证给定字符串是否为现有目录。
验证后,该值在内部存储为str
say_hello(name='world',reverse=False,repeat=1)
7
日期时间类型
cliglue.types.time.iso_date
以iso格式将给定字符串解析/验证为日期:%y-%m-%d
。
验证后,该值在内部存储为datetime.datetime
say_hello(name='world',reverse=False,repeat=1)
8
cliglue.types.time.iso_time
以iso格式将给定字符串解析/验证为时间:%h:%m:%s
。
验证后,该值在内部存储为datetime.datetime
say_hello(name='world',reverse=False,repeat=1)
9
cliglue.types.time.iso_time
以ISO格式将给定字符串解析/验证为日期时间:%y-%m-%d%h:%m:%s
。
验证后,该值在内部存储为datetime.datetime
foo@bar:~$ ./hello.py --reverse world --repeat 2Hello dlrow.Hello dlrow.
0
cliglue.types.filesystem.existing_file
验证给定字符串是否是现有的常规文件(而不是目录)。
验证后,该值在内部存储为str
cliglue.types.filesystem.existing_directory
验证给定字符串是否为现有目录。
验证后,该值在内部存储为str
cliglue.types.time.iso_date
以iso格式将给定字符串解析/验证为日期:%y-%m-%d
。 验证后,该值在内部存储为datetime.datetime
say_hello(name='world',reverse=False,repeat=1)8
cliglue.types.time.iso_time
以iso格式将给定字符串解析/验证为时间:%h:%m:%s
。 验证后,该值在内部存储为datetime.datetime
say_hello(name='world',reverse=False,repeat=1)9
cliglue.types.time.iso_time
以ISO格式将给定字符串解析/验证为日期时间:%y-%m-%d%h:%m:%s
。 验证后,该值在内部存储为datetime.datetime
foo@bar:~$ ./hello.py --reverse world --repeat 2Hello dlrow.Hello dlrow.0
示例:
foo@bar:~$ ./hello.py --reverse world --repeat 2Hello dlrow.Hello dlrow.1
foo@bar:~$ ./hello.py --reverse world --repeat 2Hello dlrow.Hello dlrow.2
cliglue.types.time.datetime_format
以用户指定的自定义格式将给定字符串解析/验证为datetime。 您可以指定多个格式,并且将按顺序分析每个格式的cli参数。 返回第一个成功分析的日期时间。 之后,该值在内部存储为datetime.datetime
foo@bar:~$ ./hello.py --reverse world --repeat 2Hello dlrow.Hello dlrow.3
foo@bar:~$ ./hello.py --reverse world --repeat 2Hello dlrow.Hello dlrow.4
cliglue.types.time.today_format
以用户指定的自定义格式将给定字符串解析/验证为时间。 它从输入中获取时间,并将其与今天的日期相结合。 您可以指定多个格式,并且将按顺序分析每个格式的cli参数。 返回第一个成功分析的日期时间。 之后,该值在内部存储为datetime.datetime
foo@bar:~$ ./hello.py --reverse world --repeat 2Hello dlrow.Hello dlrow.5
foo@bar:~$ ./hello.py --reverse world --repeat 2Hello dlrow.Hello dlrow.6
自定义类型分析器
您可以定义自定义解析器/验证器函数。
它应该接受一个str
参数并返回预期的值类型。
foo@bar:~$ ./hello.py --reverse world --repeat 2Hello dlrow.Hello dlrow.7
foo@bar:~$ ./hello.py --reverse world --repeat 2Hello dlrow.Hello dlrow.8
错误处理
cliglue
在运行时验证传递的cli参数clibuilder.run()
处理语法错误-clisyntaxerror
如果出现语法错误,clibuilder.run()
会引发clisyntaxerror
,此时:
- 缺少参数值:
--参数名
不带下一个参数 - 未提供必需的参数
- 未给出所需的位置参数
- 位置参数或参数的类型无效(存在解析类型错误)
默认情况下,由clibuilder捕获的clisyntaxerror
您可以通过在创建clibuilder时设置
reraise_error=false来禁用再次引发此错误:
clibuilder(reraise_error=false)
。
然后,控制台标准输出中将只显示错误日志。
用法错误
参数决定语法错误时应显示用法输出。
错误处理示例
foo@bar:~$ ./hello.py --reverse world --repeat 2Hello dlrow.Hello dlrow.
9
foo@bar:~$ ./hello.py world --repeat=2 --reverse
Hello dlrow.Hello dlrow.
0
clidefinitionerror
如果cli定义无效,clibuilder.run()
将引发clidefinitionerror
。例如,时间:
- 位置参数或参数设置为"必需",并设置了默认值(没有任何意义)
- 位置参数放在所有剩余参数之后
- 参数/参数值不属于严格可用选项列表
错误的cli定义示例
foo@bar:~$ ./hello.py world --repeat=2 --reverse
Hello dlrow.Hello dlrow.
1
foo@bar:~$ ./hello.py world --repeat=2 --reverse
Hello dlrow.Hello dlrow.
2
cli规则备忘表
以下是最重要的cli规则的备忘表:
foo@bar:~$ ./hello.py world --repeat=2 --reverse Hello dlrow.Hello dlrow.3
复杂的cli树
下面是一个更复杂的cli定义树示例:
多应用程序.py:
foo@bar:~$ ./hello.py world --repeat=2 --reverse Hello dlrow.Hello dlrow.4
用法:
foo@bar:~$ ./hello.py world --repeat=2 --reverse Hello dlrow.Hello dlrow.5