numpy.typing本地mypy校验通过但CircleCI报AttributeError如何排查
问题根因
这个报错和两边numpy版本一致没有关系,核心原因是numpy.typing是独立子模块,执行import numpy时不会自动加载它。
你本地运行不报错,是因为导入的pandas等依赖在初始化阶段内部已经执行过import numpy.typing——Python导入子模块时会自动给父模块挂载对应属性,相当于提前给numpy加上了typing属性,后续直接写np.typing.ndarray自然不会触发错误。但CI环境下,加载到这段带类型标注的代码前,没有任何依赖提前导入过numpy.typing,此时访问np.typing就会抛出属性不存在的错误。
另外需要注意:如果你没有开启延迟注解求值(即没有写from __future__ import annotations),Python在定义函数的瞬间就会计算返回值的类型标注,此时会直接触发对np.typing的访问,当场抛出运行时错误。
可行解决方案
任选一种即可:
- 成本最低的方案:在用到
np.typing.ndarray的文件头部加一行import numpy.typing,不需要修改现有类型标注写法,显式导入子模块后,全局访问np.typing都不会出现属性错误。 - 符合numpy官方规范的方案:直接导入专用的数组类型别名:
from numpy.typing import NDArray # 方法定义修改为 def _predict(self, X: pd.DataFrame) -> NDArray: ...
这是numpy官方推荐的数组类型标注写法,比直接写np.typing.ndarray更简洁。
- 无运行时注解解析需求的方案:在文件头部加
from __future__ import annotations,开启后所有类型注解会以字符串形式存储,不会在函数定义阶段求值,自然不会触发运行时属性访问错误。注意如果代码里存在运行时读取注解的逻辑(比如用pydantic、typeguard做运行时类型校验),该方案可能引发其他问题,谨慎选择。
补充说明
之前用np.array做类型标注时mypy报错是正常现象:np.array是用来创建数组的工厂函数,不是数组类型本身,不应该用来做类型标注,正确的数组类型标注就应该使用numpy.typing模块下的NDArray类型。
内容的提问来源于stack exchange,提问作者Sole Galli
相关产品推荐
相关产品推荐

