0

我有一组解析器和子解析器来构建生产或开发系统。如果用户选择生产,他可以添加选项,一切都很好。
如果他了解开发,他可以输入架构,然后输入构建选项。这是它变得粘稠的地方。我希望他能够选择构建选项“通信”“服务器”或“全部”,但如果他选择服务器,他有更多选择。

我的实现如下。我尝试了解析器和子解析器的组合(似乎参数只能添加到解析器,而不是子解析器,对吗?)

它分崩离析有两个原因:
1)我只能选择arch或build,我需要同时选择
2)如果我选择build,它总是要求我选择“服务器”,即使我选择另外两个中的一个。

所以我想要这样的 ./buildServer.py Dev arch -arm build -comms 或 ./buildServer.py Dev arch -arm build -server -tcp

我会很感激并能得到帮助/指导 - TIA

代码:

定义验证():

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()  
4

1 回答 1

0

aparser.add_argument(...)创建一个Action类对象,实际上是由action参数指定的子类。该动作/论点可能是positionaloptional(标记)。

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用法不允许多个子解析器(只是你显示的嵌套)。

于 2020-06-08T05:53:57.783 回答