在argparse中禁用/删除参数
问题内容:
是否可以删除或禁用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')
还是实现这一目标的另一种相对简单的方法?
另外:如果论点是位置论点,方法是否会有所不同?
注意:arg1
如此处建议的在解析后删除的问题是该参数仍显示在帮助中
问题答案:
尽管我在下面提到了错误问题,但您对的使用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
列表中查找值。在交互式外壳(我使用IPython)中运行示例解析器并查看这些对象可能会有所帮助。
同样,这似乎在一个简单的示例上起作用,但是如果与更复杂的对象(或用于生产)一起使用,则需要仔细测试。
几年前,这个话题是在Python错误/问题上提出的:
http://bugs.python.org/issue19462 Add remove_argument() method to argparse.ArgumentParser
我讨论了完全清除的困难,并提出了一些替代方法。 argparse.SUPPRESS
可以用来隐藏帮助。 optionals
如果不需要,可以忽略。
positionals
技巧比较棘手,尽管我建议调整它们的属性(nargs
和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)]
请注意,两个解析器的第二动作相同(相同的ID)。 parents
只是复制了对原始--foo
Action的引用,但没有进行复制。
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