【问题标题】:In argparse, is it possible to have source mutually exclusive args from multiple parent parsers?在 argparse 中,是否有可能来自多个父解析器的源互斥 args?
【发布时间】:2015-01-24 07:42:36
【问题描述】:

以下将设置一个互斥组,其中只有“-a”或“-b”之一有效。

import argparse

parser = argparse.ArgumentParser()
group = parser.add_add_mutually_exclusive_group()
group.add_argument('-a')
group.add_argument('-b')

我想提供来自其他解析器的“-a”和“-b”参数。比如:

a_parser = argparse.ArgumentParser()
a_parser.add_argument('-a')

b_parser = argparse.ArgumentParser()
b_parser.add_argument('-b')

parser = argparse.ArgumentParser()
group = parser.add_add_mutually_exclusive_group()
group.SOME_HOW_ADD_ARGS_FROM_OTHER_PARSER(a_parser)
group.SOME_HOW_ADD_ARGS_FROM_OTHER_PARSER(b_parser)

在这两种情况下,我希望以下内容会引发有关使用不兼容参数的异常:

parser.parse_args(['-a', '1', '-b', '1'])

问题是我不知道我缺少的“SOME_HOW_ADD_ARGS_FROM_OTHER_PARSER”逻辑是否存在。如果它确实存在,我不知道该怎么做。有人有什么想法吗?

【问题讨论】:

  • 为什么要创建多个解析器?你真正想做什么?
  • 我想创建一些适用于某些子命令的参数集。对于某些子命令,使用“-a”和“-b”是有意义的,而对于其他子命令,只有“-a”才有意义。 “-a”和“-b”选项在同一子命令中可用时应互斥。

标签: python command-line-arguments argparse


【解决方案1】:

是的,有一种方法,但它使用了解析器的一些隐藏属性。我正在使用为

开发的想法

http://bugs.python.org/issue10984argparse add_mutually_exclusive_group should accept existing arguments to register conflicts

使用 add_help=False 创建 2 个父解析器(以防止 -h 参数发生冲突 - 这是标准父解析器过程)

a_parser = argparse.ArgumentParser(add_help=False)
aaAction = a.parser.add_argument('-a')
b_parser = argparse.ArgumentParser(add_help=False)
bbAction = b_parser.add_argument('-b')

parser=argparse.ArgumentParser(parents=[a_parser, b_parser])
group=parser.add_mutually_exclusive_group()

此时parser有3个动作(参数),可以在一个'private'属性中看到,_actions

print parser._actions
""" 
[_HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None),
 _StoreAction(option_strings=['-a'], dest='a', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None),
 _StoreAction(option_strings=['-b'], dest='b', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)]
"""

第一个是它自己的help,其他的都是从父母那里继承的。我还保存了指向这些的指针,aaActionbbAction。现在我们只需要将这些添加到group_group_actions 列表中:

group._group_actions.append(parser._actions[1]) # or (aaAction)
group._group_actions.append(parser._actions[2]) # or (bbAction)

如果补丁 10984 已经实现,我们可以编写:

group = parser.add_mutually_exclusive_group(aaAction, bbAction)

这将作为创建组的一部分执行此附加。

我们可以测试它:

In [31]: print parser.format_help()
usage: ipython [-h] [-a A | -b B]

optional arguments:
  -h, --help  show this help message and exit
  -a A
  -b B


In [32]: parser.parse_args(['-a','a'])
Out[32]: Namespace(a='a', b=None)

In [33]: parser.parse_args(['-a','a','-b','b'])
usage: ipython [-h] [-a A | -b B]
ipython: error: argument -b: not allowed with argument -a
An exception has occurred, use %tb to see the full traceback.

这取决于几条信息:

  • add_argument 返回一个指向它刚刚创建的 Action 的指针。

  • parents 仅通过复制动作点(即通过引用)将动作添加到新解析器。

  • 知道parsegroup 将它们的相关操作列表存储在哪里。

  • 了解将动作添加到组与将其添加到解析器有何不同(不多)。

我建议在交互式 shell(如 IPython)中测试这样的代码,您可以在其中查看 parsergroup 的属性。并随身携带一份Lib/argparse.py 的副本。 :)

patch 10984 添加了一些代码来处理在多个组中执行操作的复杂性。通常一个动作只属于一个组。

【讨论】:

    猜你喜欢
    • 2011-06-09
    • 1970-01-01
    • 2013-03-16
    • 2011-06-13
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    相关资源
    最近更新 更多