为何argparse添加子解析器后,顶级参数位置变化会导致命令执行失败?
问题解析:argparse子命令模式下的参数错误原因
问题代码
import argparse parser = argparse.ArgumentParser(description='Bundle a Python application') parser.add_argument( '-o', '--output', metavar='OUTPUT FILE', dest='file_name', type=str, default=None) parser.add_argument( '--extensions', '--ext', action='store_const', metavar='EXTENSIONS', dest='extensions', const=True, default=False, help='Whether to allow the importing of C extensions (not needed if C extensions are optional') if 1: # 原代码为if 0,改为if 1后启用子命令 actions_parser = parser.add_subparsers( dest='action', metavar='ACTION', help='Action mod should take') actions_parser.required = True build_parser = actions_parser.add_parser("build") build_parser.add_argument( dest='root', metavar='PROJECT', type=str, help='Project path', nargs='?', default='.') get_parser = actions_parser.add_parser("get") get_parser.add_argument( dest='module', metavar='MODULE', type=str, help='Module to download') args = parser.parse_args()
现象
- 当
if 0时,无子宫命令,执行python test.py --ext正常。 - 改为
if 1启用子命令后,执行python test.py foo --ext报错。
报错原因
子命令识别错误
启用子命令后,argparse会把命令行中第一个非可选参数(foo)当作子命令,但你只定义了build和get两个合法子命令,foo不在其中,因此argparse会直接抛出“invalid choice: 'foo' (choose from 'build', 'get')”的错误。全局参数的位置问题
假设你的真实意图是执行build子命令,并把foo作为root参数,同时启用--ext,那正确的命令写法有两种:- 全局参数放在子命令之前:
python test.py --ext build foo - 若要让子命令也支持该参数,需要把
--ext的定义移到子命令的parser中(比如build_parser.add_argument(...)),此时可以写成python test.py build foo --ext
你当前的写法
python test.py foo --ext既不符合子命令的命名规则,也不符合全局参数的位置要求,因此必然报错。- 全局参数放在子命令之前:
内容的提问来源于stack exchange,提问作者DrownedSuccess
相关产品推荐
相关产品推荐

