访问传递给 argparse 参数的选项?

Accessing the choices passed to argument in argparser?

是否可以访问传递给参数的选择元组?如果是这样,我该怎么做

例如,如果我有

parser = argparse.ArgumentParser(description='choose location')
parser.add_argument(
    "--location",
    choices=('here', 'there', 'anywhere')
)
args = parser.parse_args()

我可以访问元组 ('here', 'there', 'anywhere') 吗?

事实证明 parser.add_argument 实际上是 returns 关联的 Action。您可以从中选择:

>>> import argparse
>>> parser = argparse.ArgumentParser(description='choose location')
>>> action = parser.add_argument(
...     "--location",
...     choices=('here', 'there', 'anywhere')
... )
>>> action.choices
('here', 'there', 'anywhere')

请注意,(据我所知)这在任何地方都没有记录,可能 被视为 "implementation detail",因此如有更改,恕不另行通知等。

也没有任何公开可访问的方式来获取添加后存储在 ArgumentParser 上的操作。我相信如果您愿意研究实施细节(并承担与此相关的任何风险),它们可以作为 parser._actions 使用...


最好的办法可能是为位置选择创建一个常量,然后在您的代码中使用它:

LOCATION_CHOICES = ('here', 'there', 'anywhere')

parser = argparse.ArgumentParser(description='choose location')
parser.add_argument(
    "--location",
    choices=LOCATION_CHOICES
)
args = parser.parse_args()

# Use LOCATION_CHOICES down here...

可能有更好的方法,但我在文档中没有看到任何方法。如果您知道解析器选项,您应该能够做到:

parser = argparse.ArgumentParser()
parser.add_argument("--location", choices=("here", "there", "everywhere"))

storeaction = next(a for a in parser._actions if "--location" in a.option_strings)

storeaction.choices
# ('here', 'there', 'everywhere')

正如在 mgilson 的回答中,访问 _actions 属性是未记录的,带下划线的前缀意味着 "Hey, you probably shouldn't be messing with me." 如果这在 Python.[=12 的版本之间中断,请不要感到惊讶=]

关于什么 add_argument return 的问题,如果你在像 ipython 这样的交互式会话中进行任何测试,return 会盯着你看:

In [73]: import argparse
In [74]: parser=argparse.ArgumentParser()
In [75]: parser.add_argument('foo',choices=['one','two','three'])
Out[75]: _StoreAction(option_strings=[], dest='foo', nargs=None, const=None, default=None, type=None, choices=['one', 'two', 'three'], help=None, metavar=None)
In [76]: _.choices
Out[76]: ['one', 'two', 'three']

请注意,其他方法如 add_argument_groupadd_subparsersadd_parseradd_mutually_exclusive_group 所有 return 对象都可以使用。 add_argument 没有被记录为 returning 一个对象这一事实,我认为,是一种文档疏忽。通常用户不需要使用它,但作为半开发人员我一直在使用它。 argparse 的文档不是模块能做什么或不能做什么的正式规范;它更像是一本说明手册,比教程更进一步,但显然不是参考。

parser._actions 的使用很方便,但更深入了胆量。我几乎关注了所有 bug/issues 并且想不出任何会触发此更改的内容。潜在的更改积压了大量,但由于担心会产生向后兼容性问题,开发人员已减少到近乎不动的地步。更改文档比更改 argparse.

的功能更容易