如何使用argparse处理CLI子命令 [英] How to handle CLI subcommands with argparse

查看:77
本文介绍了如何使用argparse处理CLI子命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要实现一个命令行界面,程序可以在其中接受子命令.

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>

cmd1cmd3必须与它们的至少一个选项一起使用,并且三个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.

如注释中所指出的,您可以添加将dest参数传递到

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆