如何使用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:
如果我尝试添加不带参数的subparser条目,则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.
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_default(func=do_command_one)
parser_k = subparsers.add_parser(...)
parser_k.set_default(func=do_command_k)
args = parser.parse_args()
if args.func:
args.func(args)
这篇关于如何使用argparse处理CLI子命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!