Python:argparse.Namespace 对象的类型提示

标签 python pycharm argparse type-hinting python-typing

有没有办法让 Python 静态分析器(例如,在 PyCharm 中,其他 IDE 中)在 argparse.Namespace 对象上获取 Typehints?示例:

parser = argparse.ArgumentParser()
parser.add_argument('--somearg')
parsed = parser.parse_args(['--somearg','someval'])  # type: argparse.Namespace
the_arg = parsed.somearg  # <- Pycharm complains that parsed object has no attribute 'somearg'

如果我删除内联注释中的类型声明,PyCharm 不会提示,但它也不会拾取无效属性。例如:

parser = argparse.ArgumentParser()
parser.add_argument('--somearg')
parsed = parser.parse_args(['--somearg','someval'])  # no typehint
the_arg = parsed.somaerg   # <- typo in attribute, but no complaint in PyCharm.  Raises AttributeError when executed.

有什么想法吗?


更新

灵感来自 Austin's answer下面,我能找到的最简单的解决方案是使用 namedtuples:

from collections import namedtuple
ArgNamespace = namedtuple('ArgNamespace', ['some_arg', 'another_arg'])

parser = argparse.ArgumentParser()
parser.add_argument('--some-arg')
parser.add_argument('--another-arg')
parsed = parser.parse_args(['--some-arg', 'val1', '--another-arg', 'val2'])  # type: ArgNamespace

x = parsed.some_arg  # good...
y = parsed.another_arg  # still good...
z = parsed.aint_no_arg  # Flagged by PyCharm!

虽然这令人满意,但我仍然不喜欢重复参数名称。如果参数列表显着增长,更新两个位置将是乏味的。理想的方法是以某种方式从 parser 对象中提取参数,如下所示:

parser = argparse.ArgumentParser()
parser.add_argument('--some-arg')
parser.add_argument('--another-arg')
MagicNamespace = parser.magically_extract_namespace()
parsed = parser.parse_args(['--some-arg', 'val1', '--another-arg', 'val2'])  # type: MagicNamespace

我在 argparse 模块中找不到任何可以实现这一点的东西,我仍然不确定 any 静态分析工具是否聪明足以获得这些值,而不会使 IDE 陷入停顿。

仍在搜索中...


更新 2

根据 hpaulj 的评论,我能找到的最接近上述方法的“神奇地”提取已解析对象的属性的方法是从每个解析器中提取 dest 属性_actions.:

parser = argparse.ArgumentParser()
parser.add_argument('--some-arg')
parser.add_argument('--another-arg')
MagicNamespace = namedtuple('MagicNamespace', [act.dest for act in parser._actions])
parsed = parser.parse_args(['--some-arg', 'val1', '--another-arg', 'val2'])  # type: MagicNamespace

但这仍然不会导致在静态分析中标记属性错误。如果我在 parser.parse_args 调用中传递 namespace=MagicNamespace 也是如此。

最佳答案

Typed argument parser正是为此目的而制作的。它包装了 argparse。您的示例实现为:

from tap import Tap


class ArgumentParser(Tap):
    somearg: str


parsed = ArgumentParser().parse_args(['--somearg', 'someval'])
the_arg = parsed.somearg

这是它的图片。 enter image description here

它在 PyPI 上,可以通过以下方式安装:pip install typed-argument-parser

完全披露:我是这个库的创建者之一。

关于Python:argparse.Namespace 对象的类型提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42279063/

相关文章:

python - 无法在 PyCharm 中安装 PyTorch (Python 3.9/macOS)

python argparse : How can I display help automatically on error?

python - SECRET_KEY 设置不能为空 - django+pycharm

flask - 如何使用 PyCharm 安装 Flask

python - 如何使用 argparse 处理 CLI 子命令

Python 名称错误 : name 'file_name' is not defined

python - Pandas - 合并两个部分匹配的 DataFrame

python - BeautifulSoup 选择具有特定类的某些元素中的所有 href

python - 多维数组的多维 boolean 索引

python - 使用groupby函数时如何将元素粘合到列表中?