ArgumentParser子解析器不继承已注册类型的技术问询
解决argparse子解析器无法继承主解析器自定义类型的问题
这个问题我之前也碰到过——argparse的子解析器本质是独立的ArgumentParser实例,默认并不会继承主解析器里注册的自定义类型注册表,不过有几个实用的解决办法,分享给你:
方法1:手动为子解析器同步注册自定义类型
这是最直接的方案,在创建子解析器后,手动给它注册和主解析器一样的自定义类型:
from argparse import ArgumentParser from distutils.util import strtobool parser = ArgumentParser('flats') # 主解析器注册boolean类型 parser.register('type', 'boolean', strtobool) parser.add_argument('--conveyor-belt', type='boolean') # 创建子解析器 subparsers = parser.add_subparsers() subparser = subparsers.add_parser('slaughter') # 手动给子解析器注册同样的boolean类型 subparser.register('type', 'boolean', strtobool) # 现在子解析器可以正常使用这个自定义类型了 subparser.add_argument('--auto-kill', type='boolean') # 测试一下 args = parser.parse_args(['--conveyor-belt', 'on', 'slaughter', '--auto-kill', 'off']) print(args.conveyor_belt) # 输出: True print(args.auto_kill) # 输出: False
方法2:自定义解析器类统一注册类型
如果有多个子解析器,手动注册太麻烦,可以创建一个继承自ArgumentParser的自定义类,在初始化时自动完成自定义类型的注册,然后主解析器和所有子解析器都使用这个类:
from argparse import ArgumentParser from distutils.util import strtobool class CustomArgParser(ArgumentParser): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 初始化时自动注册自定义类型 self.register('type', 'boolean', strtobool) # 主解析器使用自定义类 parser = CustomArgParser('flats') parser.add_argument('--conveyor-belt', type='boolean') # 创建子解析器时指定使用自定义类 subparsers = parser.add_subparsers(parser_class=CustomArgParser) subparser = subparsers.add_parser('slaughter') # 直接就能使用已注册的boolean类型,无需重复注册 subparser.add_argument('--auto-kill', type='boolean') # 测试验证 args = parser.parse_args(['slaughter', '--auto-kill', 'yes']) print(args.auto_kill) # 输出: True
补充说明
argparse的子解析器设计上就是独立的解析器实例,目的是让不同子命令可以有完全独立的参数规则,所以默认不会继承主解析器的类型注册表、默认参数等配置。上面两种方法分别对应“按需手动同步”和“统一模板复用”的场景,可以根据你的实际需求选择。
内容的提问来源于stack exchange,提问作者wim
相关产品推荐
相关产品推荐

