【发布时间】:2017-07-05 20:47:09
【问题描述】:
有没有办法让 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 的评论,我能找到的最接近上述方法的“神奇地”提取已解析对象的属性的方法是从每个解析器的 _actions 中提取 dest 属性。 :
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 也是如此。
【问题讨论】:
-
一个快速的谷歌说你可以在第一次使用局部变量时使用类型提示。在
parser = argparse.ArgumentParser() # type: argparse.Namespace上尝试一下,看看它是否有效。 -
@Austin:
parser在这种情况下是argparse.ArgumentParser对象,而不是argparse.Namespace对象。我希望用 args 作为属性填充parsed对象。 -
你是对的。我错过了
parsed与parser.你真正想要的似乎是 PyCharm 在构建 ArgumentParser 时解析方法参数。我怀疑这是否行得通。 -
add_argument返回它刚刚创建的Action对象。看它的属性。parser._actions是所有这些操作的列表,解析器在解析期间使用这些操作。我在之前的 SO 答案中提到过它们。 -
在您的新编辑中,您是否将新命名空间传递给
parse_args?
标签: python pycharm argparse type-hinting python-typing