在argparse中禁用/删除参数

时间:2015-09-27 11:14:34

标签: python arguments argparse

是否可以删除或禁用argparse中的参数,以便它不会显示在帮助中?怎么样?

添加新参数很容易:

parser = argparse.ArgumentParser()
parser.add_argument('--arg1', help='Argument 1')
parser.add_argument('--arg2', help='A second one')

我知道你可以通过指定“resolve”冲突处理程序来覆盖带有新定义的参数:

#In one script that should stand-alone and include arg1:

parser = argparse.ArgumentParser(conflict_handler='resolve')
parser.add_argument('--arg1', help='Argument 1')
parser.add_argument('--arg2', help='A second one')

#In another script with similar options
parser.add_argument('--arg1', help='New number 1')

但是这仍然包含帮助消息中的arg1和parse_args的结果

#Wishful thinking
#In another script with similar options, that shouldn't include arg1
parser.remove_argument('--arg1')

或另一种合理简便的方法来实现这一目标?

另外:如果参数是位置参数,方法会不同吗?

注意:解析建议here后删除arg1的问题是该参数仍显示在帮助中

4 个答案:

答案 0 :(得分:8)

  

是否可以删除或禁用argparse中的参数   它没有显示在帮助中?

添加参数时,将help设置为argparse.SUPPRESS,如下所示:

parser.add_argument('--arg1', help=argparse.SUPPRESS)

这将阻止参数显示在默认的帮助输出中。

答案 1 :(得分:3)

尽管我在下面提到了bug问题,但您对resolve的使用提出了一种可能的方法。这不适合新手或需要坚持使用公共API的人。

parser有一个Action(参数)对象列表(由add_argument创建)。

使用第二个解析器定义,其_actions列表为:

In [22]: parser._actions
Out[22]: 
[_HelpAction(option_strings=['-h', '--help'], dest='help'...),
 _StoreAction(option_strings=['--arg2'], dest='arg2', nargs=None,
      const=None, default=None, type=None, choices=None, 
      help='A second one', metavar=None),
 _StoreAction(option_strings=['--arg1'], dest='arg1', nargs=None,
      const=None, default=None, type=None, choices=None, 
      help='New number 1', metavar=None)]

当您使用resolve添加冲突的邮件时,它会删除冲突的现有操作。有关详细信息,请查看_handle_conflict_resolve方法。但是我可以在不添加新动作的情况下删除动作。

In [23]: parser._handle_conflict_resolve(None, [('--arg1',parser._actions[2])])

查看_actions并帮助确认--arg1已消失。

In [24]: parser._actions
Out[24]: 
[_HelpAction(option_strings=['-h', '--help'], dest='help',....),
 _StoreAction(option_strings=['--arg2'], dest='arg2', nargs=None,...)]

In [25]: parser.print_help()
usage: ipython3 [-h] [--arg2 ARG2]

optional arguments:
  -h, --help   show this help message and exit
  --arg2 ARG2  A second one

resolve只处理optionals,其中标志字符串可能会发生冲突。它首先删除冲突的标志,仅在没有标志的情况下删除冲突的操作。所以当你有短期和长期期权时要格外小心。

这并不涉及定位的情况。它们没有标记,它们可能共享dest个参数。 (尽管结果中只会出现一个,除非它们是附加动作)。

In [27]: foo1 = parser.add_argument('foo',help='foo 1 positional')
In [28]: foo2 = parser.add_argument('foo',help='foo 2 positional')
In [29]: parser.print_help()
usage: ipython3 [-h] [--arg2 ARG2] foo foo
positional arguments:
  foo          foo 1 positional
  foo          foo 2 positional
  ...

多玩一点,看起来我可以删除其中一个新位置:

In [33]: parser._actions[-1]
Out[33]: _StoreAction(option_strings=[], dest='foo',... help='foo 2 positional', metavar=None)
In [35]: foo2=parser._actions[-1]
In [36]: foo2.container._remove_action(foo2)
In [39]: parser.print_help()
usage: ipython3 [-h] [--arg2 ARG2] foo    
positional arguments:
  foo          foo 1 positional
 ....

如果我选择_actions[-2],我会删除第一个foo。如果我将add_argument返回的值分配给变量,例如foo1,我可以使用它而不是查找parser._actions列表中的值。在interative shell中运行示例解析器(我使用IPython)并查看这些对象可能会有所帮助。

同样,这似乎适用于一个简单的例子,但如果用于更复杂的东西(或用于制作),则需要仔细测试。

几年前就Python漏洞/问题提出了这个话题:

http://bugs.python.org/issue19462 Add remove_argument() method to argparse.ArgumentParser

我讨论了彻底清除的困难,并提出了一些替代方案。 argparse.SUPPRESS可用于隐藏帮助。如果不需要,optionals可以忽略。虽然我建议调整其属性(positionalsnargs),但default比较棘手。但是已经有一段时间了,所以我需要回顾那些帖子。

=============================

我对@2rs2ts问题感到好奇(见评论)。

我创建了一个解析器,然后将其用作另一个解析器的父级(不需要使用subparser机制)。然后我从一个解析器中删除了一个参数,并查看了另一个解析器中的更改。

使用一个参数创建父解析器:

In [59]: p=argparse.ArgumentParser()
In [60]: p.add_argument('--foo')
Out[60]: _StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)

使用parents制作另一个:

In [61]: p1=argparse.ArgumentParser(parents=[p],add_help=False)
In [62]: p1._actions
Out[62]: 
[_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=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)]

请注意,第二个Action对于两个解析器都是相同的(相同的id)。 parents刚刚复制了对原始--foo操作的引用,但它没有复制。

In [63]: id(p._actions[1])
Out[63]: 3000108652
In [64]: id(p1._actions[1])
Out[64]: 3000108652

现在使用我之前制定的技巧从一个解析器中删除'--foo':

In [65]: p1._handle_conflict_resolve(None,[('--foo',p1._actions[1])])
In [66]: p1._actions
Out[66]: [_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)]

' - foo'已从p1列表中删除,但仍显示在p列表中。但是option_strings现在是空的。

In [67]: p._actions
Out[67]: 
[_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=[], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)]

resolve代码从option_strings操作中移除了与--foo冲突的内容,然后将其从p1._actions列表中删除。但更改option_strings引用的p1也会更改p引用。

argparse使用了两种方法来区分positionalsoptionals,但解析时最常使用的方法是查看option_strings属性是否为空或不。通过清空此属性,resolve已有效地将optional转换为positional

哎呀,我的记忆不是应该的样子。:)一年前我回答了一个涉及parentsresolve的类似问题

https://stackoverflow.com/a/25821043/901925 argparse conflict resolver for options in subcommands turns keyword argument into positional argument

答案 2 :(得分:3)

删除argparse选项的功能:

def remove_options(parser, options):
    for option in options:
        for action in parser._actions:
            if vars(action)['option_strings'][0] == option:
                parser._handle_conflict_resolve(None,[(option,action)])
                break

答案 3 :(得分:0)

虽然hpaulj答案很棒,但在我的情况下,使用parser._remove_action(action)并未从“位置参数”中删除有助于删除的操作。我的解决方法是从_action_group

中删除它
def remove_option(parser, arg):
    for action in parser._actions:
        if (vars(action)['option_strings']
            and vars(action)['option_strings'][0] == arg) \
                or vars(action)['dest'] == arg:
            parser._remove_action(action)

    for action in parser._action_groups:
        vars_action = vars(action)
        var_group_actions = vars_action['_group_actions']
        for x in var_group_actions:
            if x.dest == arg:
                var_group_actions.remove(x)
                return