禁用/删除 argparse 中的参数

问题描述 投票:0回答:4

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

添加新参数很容易:

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

而且我知道您可以通过指定“解决”冲突处理程序来使用新定义覆盖参数:

#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的问题是该参数仍然显示在帮助中

python arguments argparse
4个回答
13
投票

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

添加参数时将

help
设置为
argparse.SUPPRESS
,如下所示:

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

这将防止参数出现在默认帮助输出中。


9
投票

虽然 hpaulj 的回答很好,但在我的例子中

parser._remove_action(action)
并没有从帮助中删除位置参数。它还需要从
_action_group
:

中删除
def remove_argument(parser, arg):
    for action in parser._actions:
        opts = action.option_strings
        if (opts and opts[0] == arg) or action.dest == arg:
            parser._remove_action(action)
            break

    for action in parser._action_groups:
        for group_action in action._group_actions:
            opts = group_action.option_strings
            if (opts and opts[0] == arg) or group_action.dest == arg:
                action._group_actions.remove(group_action)
                return

要删除

--bar
,请致电:

remove_argument(parser, "bar")

7
投票

删除 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

4
投票

尽管我在下面提到了错误问题,但您对

resolve
的使用提出了一种可能的方法。这不适合新手或需要坚持使用公共 API 的人。

parser
有一个动作(参数)对象列表(由
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
列表中查找值。在交互式 shell(我使用 IPython)中运行示例解析器并查看这些对象可能会有所帮助。

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


几年前就 Python 错误/问题提出了这个话题:

http://bugs.python.org/issue19462

Add remove_argument() method to argparse.ArgumentParser

我讨论了完全移除的困难,并提出了一些替代方案。

argparse.SUPPRESS
可用于隐藏帮助。
optionals
如果不需要,可以忽略。
positionals
更棘手,尽管我建议调整它们的属性(
nargs
default
)。但是已经有一段时间了,所以我需要回顾一下那些帖子。

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

我很好奇

@2rs2ts
问题(见评论)。

我做了一个解析器,然后用它作为另一个解析器的父级(不需要使用子解析器机制)。然后我从一个解析器中删除了一个参数,并查看了另一个解析器中的变化。

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

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)]

请注意,两个解析器的第二个动作是相同的(相同的 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
使用几种方法来区分
positionals
optionals
,但在解析中最常用的方法是查看
option_strings
属性是否为空。通过清空这个属性,
resolve
有效地将
optional
变成了
positional

哎呀,我的记忆力不对。:)一年前我回答了一个类似的问题,涉及

parents
resolve

https://stackoverflow.com/a/25821043/901925

argparse conflict resolver for options in subcommands turns keyword argument into positional argument

© www.soinside.com 2019 - 2024. All rights reserved.