区分python同级导入与导入函数/类

时间:2018-08-28 18:56:33

标签: python python-import python-importlib

我正在编写pylint检查器,我需要区分是同级包导入还是函数或类的导入。

同级导入示例:

from . import sibling_package

函数导入示例:

from numpy import array

我要标记后一个示例,而我想允许前一个示例,因此我需要能够分辨出两者之间的区别。

我当前正在使用:

modspec = importlib.util.find_spec('numpy', 'array')

返回一个ModuleSpec,但是我不清楚如何实现将导入array识别为模块还是功能/类的目标。在此示例中,它是函数导入,因此应进行标记。

1 个答案:

答案 0 :(得分:2)

这不是您可以轻松地从导入行中检测到 的内容。 Python是高度动态的,直到运行时您才能知道导入解析为哪种类型的对象。模块规范无法告诉您此信息,因为模块上的属性可以解析为任何内容(包括另一个模块)。

我可以看到的替代方法是:

  • 做实际的导入,然后测试对象类型。

    这并非没有风险,进口可以具有副作用。导入模块包括执行顶层语句。这些副作用可能很轻微,例如在不满足依赖项时将一个对象替换为另一个对象(try: from itertools import zip_longestexcept ImportError: from itertools import izip_longest as ziplongest是琐碎的Python 2 vs. Python 3依赖项检查),但可能会导致导入文件系统更改!

    导入也将减慢检查速度。导入numpypandas之类的模块可能会引入大量其他模块。通常,您希望保持linting fast 的速度,否则开发人员将不会理会并完全跳过lint。

  • 保留已知模块的列表。对于您知道的那些模块,请抱怨它们是否从模块而不是模块本身导入名称。这是快速的,并且将捕获大多数常见情况。您可以使用可以从要插入模块的文件系统中收集的内容来扩充列表。换句话说,目标是足够好并且接受一些新进口产品的缺失。

  • 仅在直接调用导入的名称时抱怨。注册所有导入的名称,如果AST包含该名称的Call节点,则您知道它们导入了一个函数或类。 from foo import bar,然后稍后在spam = bar('baz')上清楚地表明bar不是模块。