在 argparse 中禁用/删除参数 [英] Disable/Remove argument in argparse

查看:25
本文介绍了在 argparse 中禁用/删除参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

添加新参数很容易:

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

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

And I know you can override arguments with a new definition by specifying the "resolve" conflict handler:

#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')

但是这在帮助信息和parse_args结果中仍然包含arg1 有没有类似

But this still includes arg1 in the help message and results of parse_args Is there anything like

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

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

Or another reasonably easy way to achieve this?

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

注意:按照此处的建议解析后删除arg1的问题在于参数仍然显示在帮助中

Note: the problem with removing arg1 after parsing as suggested here is that the argument still shows in the help

推荐答案

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

Despite the bug issue I mention below, your use of resolve suggests a possible method. This is not for the novice or someone who needs to stick with the public API.

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

The parser has a list of the Action (argument) objects (as created by add_argument).

使用您的第二个解析器定义,它的 _actions 列表是:

Using your 2nd parser definition, its _actions list is:

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 方法了解详情.但是我可以愚弄它删除一个动作而不添加一个新动作.

When you add a conflicting one with resolve, it removes the existing Action that conflicts. Look at the _handle_conflict_resolve method for details. But I can fool it into removing an action without adding a new one.

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

查看 _actions 并帮助验证 --arg1 已消失.

Look at _actions and help to verify that --arg1 is gone.

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,标志字符串可能冲突的那些.它首先删除冲突的标志,只有在没有标志剩余时才删除冲突的操作.所以当你有短期和长期的选择时要格外小心.

resolve just handles optionals, ones where the flag strings might conflict. And it removes conflicting flags first, removing the conflicting action only if no flags remain. So be extra careful when you have both short and long options.

这并没有解决位置的情况.它们没有标志,它们可能共享 dest 参数.(尽管只有一个会出现在结果中,除非它们是附加操作).

And this does not address the case of positionals. They don't have flags, and they may share dest parameters. (though only one will appear in the result, unless they are appending actions).

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
  ...

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

Playing around a bit more, it looks like I can remove one of these new positionals:

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)中运行示例解析器并查看这些对象可能会有所帮助.

If I'd choosen _actions[-2] I would have removed the first foo. If I assign the value that add_argument returns to a variable, e.g. foo1, I can use that instead of looking up the value in the parser._actions list. It may be helpful to run a sample parser in an interative shell (I use IPython) and look at these objects.

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

Again, this seems to work on a simple example, but it needs careful testing if used with something more complex (or for production).

这个话题是几年前在 Python 错误/问题上提出的:

The topic was raised on the Python bugs/issues a couple of years ago:

http://bugs.python.org/issue19462 添加 remove_argument() 方法到 argparse.ArgumentParser

我讨论了完全移除的困难,并提出了一些替代方案.argparse.SUPPRESS 可用于隐藏帮助.optionals 如果不需要,可以忽略.positionals 比较棘手,不过我建议调整它们的属性(nargsdefault).但是已经有一段时间了,所以我需要查看这些帖子.

I discussed the difficulties in complete removal, and suggested some alternatives. argparse.SUPPRESS can be used to hide helps. optionals can be ignored if they aren't required. positionals are trickier, though I suggested tweaking their attributes (nargs and default). But it's been a while, so I need to review those posts.

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

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

我对 @2rs2ts 问题很好奇(见评论).

I was curious about @2rs2ts problem (see comment).

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

I made a parser, and then used it as parent to another parser (no need to use the subparser mechanism). Then I removed an argument from one parser, and looked at changes in the other parser.

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

Make a parent parser with one argument:

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)

父母再做一个:

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 Action 的引用,它没有复制.

Note that the 2nd Action is the same for both parsers (same id). parents just copied a reference to the original --foo Action, it did not make a copy.

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

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

Now remove '--foo' from one parser, using the trick I worked out before:

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 现在是空的.

'--foo' is gone from p1 list, but still present in the p list. But option_strings is now empty.

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 代码从 --foo 动作中删除了冲突的 option_strings,然后从 p1._actions 列表.但是为 p1 引用更改 option_strings 也更改了 p 引用.

The resolve code removed conflicting option_strings from the --foo action, and then removed it from the p1._actions list. But changing option_strings for the p1 reference changed the p reference as well.

argparse 使用了几种方法来区分 positionalsoptionals,但在解析中最常用的方法是看option_strings 属性是否为空.通过清空此属性,resolve 有效地将 optional 变成了 positional.

argparse uses a couple of ways to distinguish positionals from optionals, but the one used most often in parsing is to look at whether the option_strings attribute is empty or not. By emptying this attribute, resolve has effectively turned an optional into a positional.

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

Oops, my memory isn't what it should be.:) A year ago I answered a similar question involving parents and resolve

https://stackoverflow.com/a/25821043/901925子命令中选项的argparse冲突解决器将关键字参数转换为位置参数

这篇关于在 argparse 中禁用/删除参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆