如何使用 argparse 处理 CLI 子命令 [英] How to handle CLI subcommands with argparse
问题描述
我需要实现一个命令行界面,程序在其中接受子命令.
I need to implement a command line interface in which the program accepts subcommands.
例如,如果程序名为foo",则 CLI 将如下所示
For example, if the program is called "foo", the CLI would look like
foo cmd1 <cmd1-options>
foo cmd2
foo cmd3 <cmd3-options>
cmd1
和 cmd3
必须至少与它们的一个选项一起使用,并且三个 cmd*
参数总是互斥的.
cmd1
and cmd3
must be used with at least one of their options and the three cmd*
arguments are always exclusive.
我正在尝试在 argparse 中使用子解析器,但目前没有成功.问题在于 cmd2
,它没有参数:
I am trying to use subparsers in argparse, but with no success for the moment. The problem is with cmd2
, that has no arguments:
如果我尝试添加不带参数的子解析器条目,parse_args
返回的命名空间将不包含任何告诉我已选择此选项的信息(请参见下面的示例).如果我尝试将 cmd2
作为参数添加到 parser
(不是子解析器),那么 argparse 将期望 cmd2
参数将被跟随通过任何子解析器参数.
if I try to add the subparser entry with no arguments, the namespace returned by parse_args
will not contain any information telling me that this option was selected (see the example below).
if I try to add cmd2
as an argument to the parser
(not the subparser), then argparse will expect that the cmd2
argument will be followed by any of the subparsers arguments.
是否有使用 argparse
实现这一目标的简单方法?用例应该很常见……
Is there a simple way to achieve this with argparse
? The use case should be quite common…
以下是我迄今为止尝试的更接近我需要的内容:
Here follows what I have attempted so far that is closer to what I need:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help='Functions')
parser_1 = subparsers.add_parser('cmd1', help='...')
parser_1.add_argument('cmd1_option1', type=str, help='...')
parser_2 = subparsers.add_parser(cmd2, help='...')
parser_3 = subparsers.add_parser('cmd3', help='...')
parser_3.add_argument('cmd3_options', type=int, help='...')
args = parser.parse_args()
推荐答案
首先,子解析器从不插入到命名空间中.在您发布的示例中,如果您尝试将脚本运行为:
First of all subparsers are never inserted in the namespace. In the example you posted if you try to run the script as:
$python3 test_args.py cmd1 1
Namespace(cmd1_option1='1')
其中 test_args.py
包含您提供的代码(以 import argparse
开头,print(args)
结尾).
where test_args.py
contain the code you provided (with the import argparse
at the beginning and print(args)
at the end).
请注意,没有提及 cmd1
仅提及其参数.这是设计使然.
Note that there is no mention to cmd1
only to its argument. This is by design.
正如评论中指出的,您可以添加将 dest
参数传递给 add_subparsers
调用.
As pointed out in the comments you can add that information passing the dest
argument to the add_subparsers
call.
处理这些情况的常用方法是使用 set_defaults
子解析器的方法:
The usual way to handle these circumstances is to use the set_defaults
method of the subparsers:
import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help='Functions')
parser_1 = subparsers.add_parser('cmd1', help='...')
parser_1.add_argument('cmd1_option1', type=str, help='...')
parser_1.set_defaults(parser1=True)
parser_2 = subparsers.add_parser('cmd2', help='...')
parser_2.set_defaults(parser2=True)
parser_3 = subparsers.add_parser('cmd3', help='...')
parser_3.add_argument('cmd3_options', type=int, help='...')
parser_3.set_defaults(parser_3=True)
args = parser.parse_args()
print(args)
结果:
$python3 test_args.py cmd1 1
Namespace(cmd1_option1='1', parser1=True)
$python3 test_args.py cmd2
Namespace(parser2=True)
通常,不同的子解析器在大多数情况下会以完全不同的方式处理参数.通常的模式是使用不同的函数来运行不同的命令并使用 set_defaults
来设置 func
属性.当您解析参数时,您只需调用可调用对象:
In general different subparser will, most of the time, handle the arguments in completely different ways. The usual pattern is to have different functions to run the different commands and use set_defaults
to set a func
attribute. When you parse the arguments you simply call that callable:
subparsers = parser.add_subparsers()
parser_1 = subparsers.add_parser(...)
parser_1.set_defaults(func=do_command_one)
parser_k = subparsers.add_parser(...)
parser_k.set_defaults(func=do_command_k)
args = parser.parse_args()
if args.func:
args.func(args)
这篇关于如何使用 argparse 处理 CLI 子命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!