在 argparse 中禁用/删除参数 [英] Disable/Remove argument in 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
比较棘手,不过我建议调整它们的属性(nargs
和 default
).但是已经有一段时间了,所以我需要查看这些帖子.
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
使用了几种方法来区分 positionals
和 optionals
,但在解析中最常用的方法是看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
.
糟糕,我的记忆不是它应该的样子.:) 一年前我回答了一个类似的问题,涉及parents
和resolve
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屋!