Python:argparse.Namespace对象的类型提示 [英] Python: Typehints for argparse.Namespace objects

查看:518
本文介绍了Python:argparse.Namespace对象的类型提示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is there a way to have Python static analyzers (e.g. in PyCharm, other IDEs) pick up on Typehints on argparse.Namespace objects? Example:

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不会抱怨,但是它也不会选择无效的属性.例如:

If I remove the type declaration in the inline comment, PyCharm doesn't complain, but it also doesn't pick up on invalid attributes. For example:

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.

有什么想法吗?

下面奥斯汀的答案的启发,我能找到的最简单的解决方案是使用namedtuples的解决方案:

Inspired by Austin's answer below, the simplest solution I could find is one using 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对象中提取参数,如下所示:

While this is satisfactory, I still don't like having to repeat the argument names. If the argument list grows considerably, it will be tedious updating both locations. What would be ideal is somehow extracting the arguments from the parser object like the following:

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模块中找到任何可能的方法,而且我仍然不确定任何静态分析工具是否足够聪明来获取这些值而不是让IDE停顿下来.

I haven't been able to find anything in the argparse module that could make this possible, and I'm still unsure if any static analysis tool could be clever enough to get those values and not bring the IDE to a grinding halt.

仍在搜索...

根据hpaulj的评论,我能找到的与上述方法魔术"地提取已解析对象的属性的最接近的东西是将从每个解析器的_action提取dest属性的东西. :

Per hpaulj's comment, the closest thing I could find to the method described above that would "magically" extract the attributes of the parsed object is something that would extract the dest attribute from each of the parser's _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,也是如此.

But this still does not cause attribute errors to get flagged in static analysis. This is true also true if I pass namespace=MagicNamespace in the parser.parse_args call.

推荐答案

类型化参数解析器正是为此目的而制作的.它包装argparse.您的示例实现为:

Typed argument parser was made for exactly this purpose. It wraps argparse. Your example is implemented as:

from tap import Tap


class ArgumentParser(Tap):
    somearg: str


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

这里是实际情况的图片.

Here's a picture of it in action.

它在PyPI上,并且可以安装:pip install typed-argument-parser

It's on PyPI and can be installed with: pip install typed-argument-parser

完全公开:我是该库的创建者之一.

Full disclosure: I'm one of the creators of this library.

这篇关于Python:argparse.Namespace对象的类型提示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆