如何使用argparse处理CLI子命令

Ene*_*nea 5 python argparse subcommand subparsers

我需要实现一个命令行界面,程序接受子命令.

例如,如果程序名为"foo",则CLI看起来像

foo cmd1 <cmd1-options>
foo cmd2
foo cmd3 <cmd3-options>
Run Code Online (Sandbox Code Playgroud)

cmd1并且cmd3必须与其中至少一个选项一起使用,并且这三个cmd*参数始终是独占的.

我试图在argparse中使用subparser,但暂时没有成功.问题是cmd2,没有参数:

如果我尝试添加不带参数的subparser条目,则返回的命名空间parse_args将不包含任何告知我已选择此选项的信息(请参阅下面的示例).如果我尝试cmd2作为参数添加parser(而不是subparser),那么argparse会期望cmd2参数将跟随任何subparsers参数.

有没有一种简单的方法来实现这一目标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_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()
Run Code Online (Sandbox Code Playgroud)

Bak*_*riu 6

首先,从不在命名空间中插入子分析符.在您尝试运行脚本时发布的示例中:

$python3 test_args.py cmd1 1
Namespace(cmd1_option1='1')
Run Code Online (Sandbox Code Playgroud)

其中test_args.py包含您提供的代码(import argparse在开头和print(args)结尾处).

请注意,没有提及cmd1它的论点.这是设计的.

正如评论中所指出的,您可以添加将dest参数传递给add_subparsers调用的信息.

处理这些情况的常用方法是使用set_defaultssubparser 的方法:

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)
Run Code Online (Sandbox Code Playgroud)

结果如下:

$python3 test_args.py cmd1 1
Namespace(cmd1_option1='1', parser1=True)
$python3 test_args.py cmd2
Namespace(parser2=True)
Run Code Online (Sandbox Code Playgroud)

通常,不同的subparser大多数时候会以完全不同的方式处理参数.通常的模式是具有不同的功能来运行不同的命令并用于set_defaults设置func属性.解析参数时,只需调用该可调参数:

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)
Run Code Online (Sandbox Code Playgroud)