问题描述
有没有办法让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 _action
s.:
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对象的类型提示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!