我有一个带有一些子解析器的解析器。我设置了一个全局参数,用于所有子组件。以下是的相关片段
parser = argparse.ArgumentParser(prog="my_prog", add_help=False)
parser.add_argument('-d', '--debug', action='store_true', help='debug flag')
subparsers = parser.add_subparsers(dest="subparser_name", help='some help notes')
parser_cmd1 = subparsers.add_parser('cmd1', parents=[parser])
parser_cmd1.add_argument('-f', '-foo', type=str, action=foo, required=False, help='foo command')
parser_cmd2 = subparsers.add_parser('cmd2', parents=[parser])
parser_cmd2.add_argument('-b', '-bar', type=str, action=bar, required=False, help='bar command')
args = parser.parse_args()
parser = args.subparser_name
print(args)
if args.debug:
logging.basicConfig(level=logging.INFO)
if parser == 'cmd1':
if args.foo:
//do foo stuff
if parser == 'cmd2':
if args.bar:
//do bar stuff
因此,您可以使用类似my_prog.py cmd1 -d -f inp_str
的命令。问题是:subparser_name为None。打印输出(args(看起来有点像这个
Namespace(debug=True, foo="inp_str", subparser_name=None)
在添加全局调试参数之前,subpasser_name将是我运行的命令的名称,即"cmd1"或"cmd2"。现在,它是"无"。即使在子分析器的创建中添加了parents=[parser]。我该怎么解决这个问题?我怎么知道调用了哪个命令?
将公共args拆分为一个单独的ArgumentParser,然后将其用作子解析器的父级。此外,您的foo和bar选项是使用-foo和-bar指定的,whi应该是--foo和--bar。此外,您没有这些参数的默认值,因此例如,当未正确指定-f/--foo时,args.foo不存在。
这样效果更好:
import argparse
common_args = argparse.ArgumentParser(prog="my_prog", add_help=False)
common_args.add_argument('-d', '--debug', action='store_true', help='debug flag')
parser = argparse.ArgumentParser(prog="my_prog", add_help=True)
subparsers = parser.add_subparsers(dest="subparser_name", help='some help notes')
parser_cmd1 = subparsers.add_parser('cmd1', parents=[common_args])
parser_cmd1.add_argument('-f', '--foo', type=str, default='', required=False, help='foo command')
parser_cmd2 = subparsers.add_parser('cmd2', parents=[common_args])
parser_cmd2.add_argument('-b', '--bar', type=str, default='', required=False, help='bar command')
args = parser.parse_args()
parser = args.subparser_name
print(args)
if args.debug:
logging.basicConfig(level=logging.INFO)
if parser == 'cmd1':
if args.foo:
#//do foo stuff
print( f"foo {args.foo}" )
if parser == 'cmd2':
if args.bar:
#//do bar stuff
print( f"bar {args.bar}" )
运行方式:
args.py cmd1 -f asd
输出:
Namespace(subparser_name='cmd1', debug=False, foo='asd')
foo asd
更新:
如果您希望能够使用例如args.py -d cmd1
,则在创建parser
时,指定parents=[common_args]
parser = argparse.ArgumentParser(prog="my_prog", add_help=True, parents=[common_args])
下次你问问题时,请确保你只将代码作为一个最小的可复制示例发布,即可以在不添加任何东西的情况下运行
子解析器的默认值优先于主解析器设置的任何值-默认值或用户输入。main对"cmd1"执行set the subparser_name
,但子分析器将其更改回默认的None
。
虽然在测试用例中并不明显,但在两个级别上定义debug
有相同的问题。子分析器的默认值覆盖在main中设置的任何内容。
通常,在主和子分析器中使用相同的dest
不是一个好主意。标志可以相同,但dest
应该不同——至少如果您想查看main设置的任何内容。
而使用主解析器作为子解析器的parent
,只会造成混乱。