小能豆

带有子解析器和可选位置参数的 Python argparse

py

我想要一个带有子解析器的程序,它可以处理特定的参数,同时还保留一些位置和可选参数给以前的解析器(事实上我真正想要的只有一个选项,我的意思是一个有效的子解析器或一个有效的本地参数)。

我希望拥有的东西的例子:Program [{sectionName [{a,b}]}] [{c,d}]。如果提供了 sectionName,则 c/d 不兼容,反之亦然。

但是,我能实现的最好的结果就是这样test.py [-h] {sectionName} ... [{c,d}]。这意味着,argparse 不允许我在未指定有效的情况下使用位置参数 c 或 d sectionName

以下是代码:

import argparse

mainparser = argparse.ArgumentParser()
# Subparser
subparser = mainparser.add_subparsers(title="section", required=False)
subparser_parser = subparser.add_parser("sectionName")
subparser_parser.add_argument("attribute", choices=['a', 'b'], nargs='?')
# Main parser positional and optional attributes
mainparser.add_argument("attribute", choices=['c', 'd'], nargs='?')

mainparser.parse_args()

我快被这个问题搞疯了。任何帮助我都会非常感激!


阅读 24

收藏
2024-12-08

共1个答案

小能豆

你可以通过一些调整实现你想要的功能。argparse 并不直接支持在主解析器和子解析器之间共享位置参数或让它们互相排斥,但可以通过以下方式实现逻辑:

  1. 添加互斥逻辑:手动检查解析结果,确保 sectionName 和主解析器的 attribute 不同时存在。

  2. 使用条件逻辑解析:根据输入的第一个参数决定是否进入子解析器。

以下是实现的代码示例:

import argparse

def main():
    mainparser = argparse.ArgumentParser(prog="Program")
    subparser = mainparser.add_subparsers(dest="section", help="section name (optional)")

    # Subparser for sectionName
    subparser_parser = subparser.add_parser("sectionName", help="subparser for sectionName")
    subparser_parser.add_argument("attribute", choices=['a', 'b'], help="attribute for sectionName")

    # Main parser positional and optional attributes
    mainparser.add_argument("attribute", choices=['c', 'd'], nargs='?', help="attribute for main parser")

    # Parse arguments
    args = mainparser.parse_args()

    # Validate mutual exclusivity
    if args.section == "sectionName" and args.attribute:
        mainparser.error("Cannot specify both 'sectionName' and main attribute ('c' or 'd').")

    # Handle parsed arguments
    if args.section == "sectionName":
        print(f"Section: sectionName, Attribute: {args.attribute}")
    else:
        print(f"Main Attribute: {args.attribute}")

if __name__ == "__main__":
    main()

示例运行

情况 1:仅提供 sectionName

$ python test.py sectionName a
Section: sectionName, Attribute: a

情况 2:仅提供主属性

$ python test.py c
Main Attribute: c

情况 3:同时提供 sectionName 和主属性(无效)

$ python test.py sectionName a c
usage: Program [-h] {sectionName} ... [attribute]
Program: error: Cannot specify both 'sectionName' and main attribute ('c' or 'd').

关键点

  1. dest 参数
  2. add_subparsers 中指定 dest,让 args.section 存储用户选择的子解析器名称。

  3. 手动验证冲突

  4. 使用 args.sectionargs.attribute 检查两者是否冲突。

  5. 友好的错误消息

  6. 使用 mainparser.error 提供清晰的错误反馈,而不是直接崩溃。

这种方法满足了你对互斥逻辑的需求,同时保持了灵活性。

2024-12-08