Python argparse和互斥组,每个组都有自己所需的设置

Python argparse和互斥组,每个组都有自己所需的设置,python,python-3.x,argparse,mutual-exclusion,Python,Python 3.x,Argparse,Mutual Exclusion,我有一个程序,需要有一个选项来测试服务器ID列表或针对服务器发出命令。这意味着,如果我发布了-test,那么就不需要其他任何东西了。它对每台服务器运行所有测试并打印结果 但是,如果我没有指定-test,那么它应该需要一些选项,比如-id和-command 但是,我不确定argparse是否能够处理互斥组中所需的选项。为简单起见修改的代码如下所示。我已经修改了选项,所以如果您指定-a,那么您应该可以继续,不需要其他选项 import argparse parser = argparse.Argu

我有一个程序,需要有一个选项来测试服务器ID列表或针对服务器发出命令。这意味着,如果我发布了-test,那么就不需要其他任何东西了。它对每台服务器运行所有测试并打印结果

但是,如果我没有指定-test,那么它应该需要一些选项,比如-id和-command

但是,我不确定argparse是否能够处理互斥组中所需的选项。为简单起见修改的代码如下所示。我已经修改了选项,所以如果您指定-a,那么您应该可以继续,不需要其他选项

import argparse

parser = argparse.ArgumentParser()

test_or_not = parser.add_mutually_exclusive_group(required=True)
test_or_not.add_argument('-a', action='store_true')
or_not = test_or_not.add_argument_group()
target = or_not.add_mutually_exclusive_group(required=True)
target.add_argument('-b',action="store_true")
target.add_argument('-c',action="store_true")
target.add_argument('-d',action="store_true")
target.add_argument('-e',action="store_true")
group = or_not.add_mutually_exclusive_group(required=True)
group.add_argument('-f',action="store_true")
group.add_argument('-g',action="store_true")
or_not.add_argument('-i',action="store_true")
or_not.add_argument('-j',action="store_true")
or_not.add_argument('-k',action="store_true")
or_not.add_argument('-l',action="store_true")

args = parser.parse_args()
产生结果错误的原因是argparse仍然需要单独的选项,即使它们位于相互排斥的组中。有没有一种方法可以让argparse适应这组选项,或者我需要在argparse之外添加一些编程

编辑:我可以添加一个完全在argparse之外工作的新选项,如下所示,但如果可能的话,我希望它在argparse中保持结构化

import argparse
import sys

if '--test' in sys.argv:
    go_do_testing()
    sys.exit(0)

parser = argparse.ArgumentParser()
<snip>

正如评论中所建议的,如果您希望拥有互斥的测试和运行逻辑,那么应该使用子parser。以下是这一想法的说明:

#!/usr/bin/env python3
"""
Script to test or run commands on given servers.
./the_script.py test  # To test all servers
./the_script.py run --id 127.0.0.1 --command "echo hello world"
"""
from argparse import ArgumentParser, RawDescriptionHelpFormatter as RDHF


def test_servers(servers):
    """
    Given a list of servers, let's test them!
    """
    for server in servers:
        print('Just tested server {s}'.format(s=server))

def do_actual_work(server_id, command):
    """
    Given a server ID and a command, let's run the command on that server!
    """
    print('Connected to server {s}'.format(s=server_id))
    print('Ran command {c} successfully'.format(c=command))


if __name__ == '__main__':
    parser = ArgumentParser(description=__doc__, formatter_class=RDHF)
    subs = parser.add_subparsers()
    subs.required = True
    subs.dest = 'run or test'
    test_parser = subs.add_parser('test', help='Test all servers')
    test_parser.set_defaults(func=test_servers)
    run_parser = subs.add_parser('run', help='Run a command on the given server')
    run_parser.add_argument('-i', '--id',
                            help='The ID of the server to connect to and run commands',
                            required=True)
    run_parser.add_argument('-c', '--command',
                            help='The command to run',
                            required=True)
    run_parser.set_defaults(func=do_actual_work)
    args = parser.parse_args()
    
    if args.func.__name__ == 'test_servers':
        all_servers = ['127.0.0.1', '127.0.0.2']
        test_servers(all_servers)
    else:
        do_actual_work(args.id, args.command)
该脚本设置互斥和必需的子parser test and run。对于测试子Parser,不需要其他任何东西。但是,对于run子parser,需要-id和-command。每个子parser都与其指定的目标函数相关联。为了简单起见,我将test_解析器绑定到test_服务器;而run_解析器与do_实际工作相关联

此外,您应该能够按如下方式调用脚本以运行所有测试:

./the_script.py test
要在特定服务器上运行特定命令,请按如下方式调用脚本:

./the_script.py run --id 127 --command "echo hello world"

我希望这证明是有用的。

您能将测试选项设置为子parser并将子parser绑定到检查这些服务器的功能上吗?我不知道这是一件事。我发誓我已经阅读并引用了100多次argparse文档,但天哪,我从来没有注意到这一点。我确实觉得有点傻…哈哈。如果它接近于帮助你尝试做的事情,而你在这里找不到重复的,那么请随意写一个答案来分享你的发现。我正打算对你说同样的话。请回答这个问题,这样我就可以接受了。如果看起来不错,也可以贴在这里。
./the_script.py run --id 127 --command "echo hello world"