我正在编写一个 pylint 检查器,我需要区分包的同级导入和函数或类的导入。
同级导入示例:
from . import sibling_package
函数导入示例:
from numpy import array
我想标记后一个示例,而我想允许前一个示例,因此我需要能够区分两者之间的区别。
我目前正在使用:
modspec = importlib.util.find_spec('numpy', 'array')
这会返回一个ModuleSpec
,但我不清楚如何实现将导入array
识别为模块与函数/类的目标。在本例中,它是一个函数导入,因此应该被标记。
最佳答案
这不是您可以仅从导入行轻松检测到的东西。 Python 是高度动态的,直到运行时你才能知道导入解析为什么类型的对象。模块规范无法告诉您此信息,因为模块上的属性可以解析为任何内容(包括另一个模块)。
我可以看到的替代方案是:
进行实际导入,然后测试对象类型。
这并非没有风险,进口可能有副作用。导入模块包括执行顶层语句。这些副作用可能很轻微,例如在不满足依赖项时将一个对象替换为另一个对象(
try: from itertools import zip_longest
,except ImportError: from itertools import izip_longest as ziplongest
是一个简单的 Python 2 与 Python 3 依赖项检查),但导入可能会导致文件系统更改!导入也会减慢检查速度。导入类似
numpy
的模块或pandas
可以引入大量附加模块。您通常希望保持 linting 快速,否则开发人员往往不会费心并完全跳过 linting。保留已知模块的列表。对于您了解的那些模块,如果它们从模块导入名称而不是模块本身,请提示。这速度很快,并且可以捕获大多数常见情况。您可以使用从正在检查的模块周围的文件系统中收集到的内容来扩充列表。换句话说,目标是足够快且足够好,并接受新导入的一些失误。
仅在直接调用导入的名称时才会提示。注册所有导入的名称,如果 AST 包含
Call
该名称的节点那么您就知道他们导入了函数或类。from foo import bar
,然后是spam = bar('baz')
是一个明确的指标bar
不是一个模块。
关于python - 区分 python 同级导入与导入函数/类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52064613/