如何让作为子解析器父解析器的参数组互斥组正确显示帮助
argparse子命令继承父解析器时,互斥组无法正确显示在自定义参数组中
在argparse中,我们可以将互斥组添加到带有自定义标题和描述的参数组中,但当将该父解析器作为subparsers的parents参数使用时,互斥组不会出现在对应的参数组帮助文本里,反而被归类到默认的options组中。
复现代码
from argparse import ArgumentParser parent_parser = ArgumentParser(add_help=False) parent_parser.add_argument('--common') parent_parser_group = parent_parser.add_argument_group('New Group', 'Description.') parent_parser_group.add_argument('--non-mut') meg = parent_parser_group.add_mutually_exclusive_group() meg.add_argument('--mut1', dest='mut') meg.add_argument('--mut2', dest='mut') parser = ArgumentParser(description='The main parser.') subparsers = parser.add_subparsers(dest='subcommand', required=True) command1_parser = subparsers.add_parser('command1', parents=[parent_parser]) command1_parser.add_argument('--c1') command2_parser = subparsers.add_parser('command2', parents=[parent_parser]) command2_parser.add_argument('--c2') command1_parser.print_help()
当前实际输出
usage: argparse_debug.py command1 [-h] [--common COMMON] [--non-mut NON_MUT] [--mut1 MUT | --mut2 MUT] [--c1 C1] options: -h, --help show this help message and exit --common COMMON --mut1 MUT --mut2 MUT --c1 C1 New Group: Description. --non-mut NON_MUT
预期输出
usage: argparse_debug.py command1 [-h] [--common COMMON] [--non-mut NON_MUT] [--mut1 MUT | --mut2 MUT] [--c1 C1] options: -h, --help show this help message and exit --common COMMON --c1 C1 New Group: Description. --mut1 MUT --mut2 MUT --non-mut NON_MUT
注意:直接调用parent_parser.print_help()可以得到预期的格式,说明问题出在父解析器被继承到子命令时的配置复制环节。
解决方案
问题的根源是argparse在处理parents继承时,没有正确保留互斥组与自定义参数组的关联关系,导致互斥组被默认归类到options组中。我们可以手动调整子解析器中动作组的归属,将互斥组移回目标自定义参数组。
修改后的代码
from argparse import ArgumentParser def fix_mutually_exclusive_group(parent_parser, child_parser, target_group_title): """将父解析器中指定参数组内的互斥组移到子解析器的对应参数组中""" # 从父解析器中获取目标参数组内的互斥组动作 mut_actions = [] for group in parent_parser._action_groups: if group.title == target_group_title: # 遍历参数组内的互斥组 for action in group._group_actions: if hasattr(action, '_mutually_exclusive'): mut_actions.extend(action._mutually_exclusive._group_actions) break # 找到子解析器中的目标参数组和默认options组 target_group = next(g for g in child_parser._action_groups if g.title == target_group_title) default_group = next(g for g in child_parser._action_groups if g.title == 'options') # 将互斥组动作从默认组移到目标参数组 for action in mut_actions: if action in default_group._actions: default_group._actions.remove(action) target_group._actions.append(action) # 定义父解析器 parent_parser = ArgumentParser(add_help=False) parent_parser.add_argument('--common') parent_parser_group = parent_parser.add_argument_group('New Group', 'Description.') parent_parser_group.add_argument('--non-mut') meg = parent_parser_group.add_mutually_exclusive_group() meg.add_argument('--mut1', dest='mut') meg.add_argument('--mut2', dest='mut') # 定义主解析器和子命令 parser = ArgumentParser(description='The main parser.') subparsers = parser.add_subparsers(dest='subcommand', required=True) command1_parser = subparsers.add_parser('command1', parents=[parent_parser]) command1_parser.add_argument('--c1') # 修复互斥组归属 fix_mutually_exclusive_group(parent_parser, command1_parser, 'New Group') command2_parser = subparsers.add_parser('command2', parents=[parent_parser]) command2_parser.add_argument('--c2') # 修复互斥组归属 fix_mutually_exclusive_group(parent_parser, command2_parser, 'New Group') command1_parser.print_help()
运行这段代码后,子命令的帮助文本就会按照预期显示,互斥组会被正确归类到自定义的New Group参数组中。
内容的提问来源于stack exchange,提问作者Phoenix
相关产品推荐
相关产品推荐

