带有多级解析器/子解析器的 Argparse 可选参数
Posted
技术标签:
【中文标题】带有多级解析器/子解析器的 Argparse 可选参数【英文标题】:Argparse optional arguments with multilevel parser/subparser 【发布时间】:2020-09-26 18:06:09 【问题描述】:我有一组解析器和子解析器来构建生产或开发系统。 如果用户选择生产,他可以添加选项,一切都很好。 如果他了解开发,他可以输入架构,然后输入构建选项。 这是它变得粘稠的地方。 我希望他能够选择构建选项 'comms' 'server' 或 'all',但如果他选择服务器,他有更多选择。
我的实现如下。我尝试了解析器和子解析器的组合 (看来参数只能添加到解析器,不能添加子解析器,对吗?)
它分崩离析有两个原因: 1)我只能选择arch或build,我需要同时选择 2)如果我选择构建它总是要求我选择“服务器”,即使我选择其他两个之一。
所以我想要这样的东西 ./buildServer.py 开发架构 -arm build -comms 要么 ./buildServer.py Dev arch -arm build -server -tcp
我将不胜感激并能获得帮助/指导 - TIA
代码:
def 验证():
main_parser = argparse.ArgumentParser()
main_subparsers = main_parser.add_subparsers(title="main", dest="main_command")
# parser production choices
prod_parser = main_subparsers.add_parser("prod", help="Prod")
prod_parser.add_argument("-c", "--change", action='store_true', dest="change_sig", default=False, help="Change signature information (default = %(default)s)")
prod_parser.add_argument("-sd", "--sign-deb", action='store_true', dest="sign_deb", default=False, help="Add signature to the .deb file (default = %(default)s)")
prod_parser.add_argument ("-i", "--install", action='store_true', dest="build_deb" , default=False, help="Build .deb file from existing structure (default = %(default)s)")
# parser for development
dev_parser = main_subparsers.add_parser("Dev", help="Dev")
dev_subparser = dev_parser.add_subparsers(title="devsubparser")
# optional development architecture choices
action_arch_parser = dev_subparser.add_parser("arch", help="architecture")
dev_arch_group = action_arch_parser.add_mutually_exclusive_group()
dev_arch_group.add_argument("-x86", action='store_const', dest="architecture", const='x', default='x',help="Build dev code on X86")
dev_arch_group.add_argument("-arm", action='store_const', dest="architecture", const='a', help="Build dev code on arm")
# development build choices - 2 arguments (coms / all) and a third (server) that has its own options.
dev_build_parser = dev_subparser.add_parser("build", help="build")
dev_build_parser.add_argument("-comms", action='store_true', help="Build comms program")
dev_build_parser.add_argument("-all", action='store_true', help="Build all programs")
server_parser = dev_build_parser.add_subparsers(title="server", help="server subparser")
server_parser_p = server_parser.add_parser("server", help="server parser")
server_parser_p.add_argument("-tcp", help="tcp option")
server_parser_p.add_argument("-fips", help="fips option")
server_parser_p.add_argument("-sim", help="sim option")
args = main_parser.parse_args()
【问题讨论】:
【参考方案1】:aparser.add_argument(...)
创建一个Action
类对象,实际上是action
参数指定的子类。该动作/参数可能是positional
或optional
(已标记)。
sp=aparse.add_subparsers(...)
是add_argument
的专用版本,它创建了子解析器类的Action
。 print(sp)
将显示它的一些属性。这实际上是一个positional
参数,带有choices
属性。
p1 = sp.add_parser(...)
创建一个argparse.ArgumentParser()
对象,并将其链接到放在sp.choices
列表中的名称。解析器作为p1
变量返回。
p1.add_argument(...)
定义了一个动作/参数,就像使用主解析器一样。
因此,在解析过程中,输入 (sys.argv
) 像往常一样被一一处理。但是,当它遇到与“p1”的位置和名称匹配的字符串时,解析任务将传递给p1
(以及sys.argv
列表的剩余部分)。当p1
到达sys.argv
的末尾时,其命名空间和控制权将传递给父解析器。父级不做任何进一步的解析。
在您的情况下,您可以向下传递几个级别的解析器。 (术语,解析器和子解析器可能有点混乱,至少在描述中。它们在代码中明确定义。)
这种子解析器机制只允许一个选择(在每个级别)。这不是一个多级树横向工具。你去一个特定的线程结束,然后备份。
所以
./buildServer.py Dev arch -arm build -comms 或 ./buildServer.py Dev arch -arm build -server -tcp
main_parser (sees 'Dev', passes control to:)
dev_parser (sees 'arch', passes control to:)
action_arch_parser
(sees -arm - sets the const)
(doesn't have any positional to handle 'build'
returns with an unrechognized arguments)
可能有解决此问题的方法 - 我或其他人在之前的 SO 中提出过类似的建议 - 但直接使用 argparse
不允许使用多个子解析器(只是您显示的嵌套)。
【讨论】:
感谢 hpaulj 我感谢您的解释。非常清楚。我现在了解@augurar 关于如何使用 python argparse 解析多个嵌套子命令的评论? ***.com/questions/10448200/… 关于嵌套和并行命令。那篇文章中的任何答案对我想做的事情有用吗?看起来答案将涉及拆分 argv?你能指点我(希望不要复杂)的建议吗?再次感谢! 有没有办法使用 parse_known_args 并分别解析服务器选项?以上是关于带有多级解析器/子解析器的 Argparse 可选参数的主要内容,如果未能解决你的问题,请参考以下文章
argparse:声明全局参数后无法获取 subparser_name