我正在试图弄清楚如何使用pythons arparse库在子解析器场景中添加全局选项。
现在我的代码看起来像这样:
def parseArgs(self):
parent_parser = argparse.ArgumentParser(add_help=False)
parent_parser.add_argument('--debug', default=False, required=False,
action='store_true', dest="debug", help='debug flag')
main_parser = argparse.ArgumentParser()
main_parser.add_argument('--debug', default=False, required=False,
action='store_true', dest="debug", help='debug flag')
service_subparsers = main_parser.add_subparsers(title="category",
dest="category")
agent_parser = service_subparsers.add_parser("agent",
help="agent commands", parents=[parent_parser])
return main_parser.parse_args()
这适用于命令行./test --help
,--debug
选项列为全局:
usage: test [-h] [--debug] {agent} ... optional arguments: -h, --help show this help message and exit --debug debug flag category: {agent} agent agent commands
但是,当我使用命令行./test agent --help
触发代理子解析器时,--debug
选项现在不再作为全局选项列出,而是作为子解析器的选项。此外,它现在必须指定为./test agent --debug
,而./test --debug agent
不再有效:
usage: test agent [-h] [--debug] optional arguments: -h, --help show this help message and exit --debug debug flag
我希望能够做的是定义--debug
是全局的,因此可以始终为所有子解析器指定它,并在帮助输出中正确地列出。
答案 0 :(得分:3)
main_parser
将默认值填入namespace
(False
的{{1}});如果遇到debug
,则会将--debug
更改为debug
。当它看到True
字符串时,它会调用subparser,将剩余的参数字符串和它一直使用的命名空间传递给它。
现在subparser执行正常的解析器操作 - 如果填写其参数的默认值,则将agent
设置为default
。如果在剩余字符串中遇到False
,则会将其更改为--debug
。否则它会保持原样。完成后,它会将命名空间传递回主解析器,然后主解析器将其返回给您的代码。
所以
True
myprog.py --debug agent --debug
已从False翻转为True变为False并返回True。
这是为主解析器共享相同namespace(debug=False)
的结果(我不喜欢在此上下文中使用' global')和subparser。
有一个错误/问题试图稍微改变行为,将子分析符传递给处女'命名空间,然后以某种方式将其结果与主结果合并。但这产生了一些向后兼容性问题。如果需要,我可以查一查。
目前,尝试在主分析器和子分析器中定义相同的可选项,必然会给您和您的用户造成混淆。
如果我将父母改为
dest
(不需要默认值,或者如果与选项标志相同则为dest)
生成的命名空间看起来像
parent_parser.add_argument('--Debug', action='store_true', help='debug flag')
或者我可以定义
1721:~/mypy$ python stack37933480.py --debug agent --Debug
Namespace(Debug=True, category='agent', debug=True)
并获得:
parent_parser.add_argument('--debug', dest='debug1', action='store_true', help='debug flag')
两个地方都有相同的标志,但命名空间中的条目不同。解析后我可以做类似的事情:
1724:~/mypy$ python stack37933480.py --debug agent --debug
Namespace(category='agent', debug=True, debug1=True)
统一两面旗帜。您的用户将看到' - debug'无论有什么帮助要求。
很抱歉,如果描述有点冗长,但我认为首先了解这种行为很重要。然后解决方案变得更加明显。
在这种情况下,使用父母并不会使问题复杂化。我假设您正在使用它只是为了将调试添加到所有子分析器。
另一个选择是为主解析器定义args.debug = args.debug or args.debug1
。是的,subparsers帮助中缺少它,但您始终可以在说明中添加注释。
===================
subparser定义采用debug
参数。如果没有给出,则根据主prog
定义。
如果我将prog
添加为:
prog
subparser用法变为:
agent_parser = service_subparsers.add_parser("agent",
prog='myprog.py [--debug] agent',
help="agent commands", parents=[parent_parser])
或者我可以将1824:~/mypy$ python3 stack37933480.py agent -h
usage: myprog.py [--debug] agent [-h] [--debug]
添加到prog
定义
add_subparsers
检查该方法的代码,了解它如何构造默认用法前缀。它包括service_subparsers = main_parser.add_subparsers(title="category",
prog='myprog.py [--debug]',
dest="category")
位置,但不包括选项。
http://bugs.python.org/issue9351 - 在这个补丁中,原始开发人员认为用户希望参数的subparser定义应该覆盖主解析器的值和操作。另一方面,您希望主要定义具有优先权。
http://bugs.python.org/issue24251 - 但9351中提出的更正给其他用户带来了问题。这就是为什么我认为最好不要在main和sub中定义相同的main
。很难满足每个人的期望。