在argparse中禁用/删除参数

Bry*_*n P 17 python arguments argparse

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

添加新参数很容易:

parser = argparse.ArgumentParser()
parser.add_argument('--arg1', help='Argument 1')
parser.add_argument('--arg2', help='A second one')
Run Code Online (Sandbox Code Playgroud)

我知道你可以通过指定"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')
Run Code Online (Sandbox Code Playgroud)

但这仍然包括帮助消息中的arg1和结果parse_args是否有类似的东西

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

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

另外:如果论证是位置论证,那么方法会不同吗?

注:排除故障arg1解析的建议后,这里是参数仍显示在帮助

小智 10

虽然 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
Run Code Online (Sandbox Code Playgroud)

要删除--bar,请调用:

remove_argument(parser, "bar")
Run Code Online (Sandbox Code Playgroud)

  • 该代码没有使用示例。您必须传递一个不带前导破折号的参数才能使其正常工作,例如要删除 `--bar`,请调用 `remove_option(parser, "bar")` (2认同)

Bur*_*lid 9

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

设置helpargparse.SUPPRESS添加参数时,如下所示:

parser.add_argument('--arg1', help=argparse.SUPPRESS)
Run Code Online (Sandbox Code Playgroud)

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

  • 这仍将*解析*参数,例如,如果它被标记为这样,则需要它. (3认同)

小智 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
Run Code Online (Sandbox Code Playgroud)

  • 有趣的。这是否会从帮助中删除它并阻止选项被解析?您可以添加更多解释和示例吗? (3认同)

hpa*_*ulj 5

尽管我在下面提到了错误问题,但您的使用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)]
Run Code Online (Sandbox Code Playgroud)

当您添加一个与 冲突的操作时resolve,它会删除存在冲突的现有操作。详细看_handle_conflict_resolve方法。但是我可以愚弄它删除一个动作而不添加一个新动作。

In [23]: parser._handle_conflict_resolve(None, [('--arg1',parser._actions[2])])
Run Code Online (Sandbox Code Playgroud)

查看_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
Run Code Online (Sandbox Code Playgroud)

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
  ...
Run Code Online (Sandbox Code Playgroud)

多玩一点,看起来我可以删除这些新位置之一:

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
 ....
Run Code Online (Sandbox Code Playgroud)

如果我选择,_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更棘手,但我建议调整它们的属性(nargsdefault)。但是已经有一段时间了,所以我需要查看这些帖子。

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

我对@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)
Run Code Online (Sandbox Code Playgroud)

制作另一个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)]
Run Code Online (Sandbox Code Playgroud)

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

In [63]: id(p._actions[1])
Out[63]: 3000108652
In [64]: id(p1._actions[1])
Out[64]: 3000108652
Run Code Online (Sandbox Code Playgroud)

现在使用我之前制定的技巧从一个解析器中删除“--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)]
Run Code Online (Sandbox Code Playgroud)

'--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)]
Run Code Online (Sandbox Code Playgroud)

resolve代码中删除冲突的option_strings--foo动作,然后从删除它p1._actions列表。但改变option_stringsp1参考改变了p基准为好。

argparse采用了几种方法来区分positionalsoptionals,但最常用的解析一来是看看是否option_strings属性为空。通过清空此属性,resolve已有效地将 anoptional变成了positional

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

/sf/answers/1807473041/ argparse conflict resolver for options in subcommands turns keyword argument into positional argument

  • 这对子解析器造成了严重破坏。我有一个基础子解析器和一堆其他将这个基础标记为它们的“父”的子解析器。如果我从一个子解析器中删除了一个可选参数,那么所有其他子解析器仍然有这个参数......但它变成了位置(但在他们的帮助消息中显示为可选,仍然!)同样的事情也发生在 Burhan 的方法上,所以它是可能是图书馆的限制。 (2认同)