【问题标题】:argparse update choices of an argumentargparse 更新参数的选择
【发布时间】:2019-04-30 15:10:12
【问题描述】:

使用 argparse,在将参数添加到解析器后,有什么方法可以更新参数的“选择”选项? Argparse documentation 对更新选择没有太多帮助

import argparse

parser = argparse.ArgumentParser()

choices_list = ['A', 'B']
parser.add_argument('arg1', choices=choices_list)

# The list of choices now changes 
choices_list = ['A', 'C', 'D']

# Some code to update 'arg1' choices option ?
parser.???

我尝试将“parser.add_argument”与新的“choices_list”一起使用,但它会创建重复的参数。

使用 Python 3.7

【问题讨论】:

  • 发生这种情况时,您是否有理由不构建全新的解析器?如果它是由函数构建的,则可以将可以更改的内容作为参数提供。
  • 除非您多次使用解析器(可能调用parse_known_args,并在调用之前更新choices_list 或再次parse_args),否则将参数添加到直到你知道choices_list 的最终值。参数解析器通常是相当静态的,在您实际执行任何类型的 I/O 之前就已完全定义。
  • @CharlesDuffy 我没有理由不能构建一个新的解析器。我只是觉得修改一个属性比重新创建一个全新的对象更干净。
  • @chepner 也许我没有为此使用正确的工具,但我有一个交互式 shell(使用 cmd2),并且某些选项的选择取决于以前的操作。我事先不知道我将要展示什么,但是当交互式 shell 启动时我需要有一些默认选择

标签: python argparse


【解决方案1】:

参数本身有一个choices 属性,但如果您保存对参数的引用而不是尝试从解析器本身检索它,这是最简单的。 (否则,您必须通过私有属性parser._actions 扫描并尝试确定您需要哪个。)

import argparse

parser = argparse.ArgumentParser()

choices_list = ['A', 'B']
arg1 = parser.add_argument('arg1', choices=choices_list)

arg1.choices = ['A', 'B', 'D']

【讨论】:

  • 我确认它确实有效,但使用 pycharm,触发了一个弱警告 -> “函数 'add_argument' 不返回任何内容”。在 argparse.pyi 中,我可以看到“add_argument”不需要返回值。知道为什么会这样记录吗?
  • 不知道。有人可能会说您不应该依赖 add_argument 返回任何东西,因为它没有记录在案,但它似乎永远不会改变。
  • add_argument 返回Action 对象的事实不在文档中,但是很多细节都没有记录。但从代码中可以明显看出,在交互式会话中测试argparse 时也很明显。 argparse 文档与其说是正式的规范,不如说是一个操作文档。
【解决方案2】:

看着https://github.com/python/typeshed/blob/master/stdlib/2and3/argparse.pyi

# undocumented
class _ActionsContainer:

    def add_argument(self,
                 ...
                 **kwargs: Any) -> Action: ...

    def add_argument_group(self, *args: Any, **kwargs: Any) -> _ArgumentGroup: ...

我不使用pycharm,但我很困惑为什么它会抱怨add_argument,而不是add_argument_group。

argparse 文档没有提到返回的Action 对象,但那是因为用户通常不需要访问它。但是在交互式测试时,它非常明显:

In [93]: import argparse
In [94]: parser = argparse.ArgumentParser()
In [95]: parser.add_argument('--foo', choices=['one','two'])
Out[95]: _StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=['one', 'two'], help=None, metavar=None)
In [96]: _.choices
Out[96]: ['one', 'two']

以前的 SO 答案指出 Actions 也可在“隐藏”_actions 列表中使用。但是在 Python 中,'_' 只是一个非正式的约定。口译员不强制执行隐私。

In [98]: parser._actions
Out[98]: 
[_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=['one', 'two'], help=None, metavar=None)]

显示的是Action 对象的字符串表示形式。这些是最常用的属性。

argparse 的文档不是正式的 API 参考;这太不完整了。它更像是一个高级操作文档,比教程更复杂,但不如正式规范那么完整。

【讨论】:

  • 出于某种原因,我有一个不同的argparse.pyi pastebin。查看第 79 行,我知道 PyCharm 不期望返回值,但我不明白为什么首先添加了 -> None # weirdly documented for add_argument
猜你喜欢
  • 2015-12-11
  • 1970-01-01
  • 2013-05-14
  • 1970-01-01
  • 1970-01-01
  • 2020-11-03
  • 2021-01-07
  • 1970-01-01
  • 2019-07-12
相关资源
最近更新 更多