Sphinx 和 autodoc:numpy.core.multiarray 导入失败 + mock 具有不受支持的操作数类型

Sphinx and autodoc: numpy.core.multiarray failed to import + mock has unsupported operand type

我正在尝试为我的项目构建文档 (https://github.com/pyMatJ/S4Utils) using sphinx and autodoc, targeting RtD eventually (https://s4utils.readthedocs.io/en/latest/)。

到目前为止,我设法使整个项目可安装,我认为我的 setup.py 是正确的。但是,我无法让 sphinx 使用 autodoc 正确生成文档。我使用 virtualenvwrapper 设置了一个干净的 python3.6 venv,只安装了 sphinx 和我的包并尝试编译文档 (make html)。带有手动输入(安装等)的页面以及一个自动记录的模块(https://s4utils.readthedocs.io/en/latest/epsInterpolator.html)工作正常。 但是,大部分 autodoc 作业仍然缺失(应该记录另外两个模块),并且我收到一堆关于 autodoc 无法导入模块的警告。最终看起来它归结为两个主要错误:

hbar_eV = h_eV/(2*np.pi)
TypeError: unsupported operand type(s) for *: 'int' and 'Mock'

从一个模块在其序言中导入 numpy 并使用它来定义变量

以及

numpy.core.multiarray failed to import for both modules.

RtD 和干净的 venv 都重现了错误。我检查过只安装了一个版本的 numpy(最新版本,1.19.1)。我使用 conf.py 文件导入模拟,并模拟相关的(我想)模块:

from unittest.mock import Mock as MagicMock
MOCK_MODULES = ['numpy', 'matplotlib.pyplot', 'matplotlib.gridspec', 'matplotlib.widgets', 'pyvista']
for mod_name in MOCK_MODULES:
    sys.modules[mod_name] = MagicMock()

我将文件路径添加到 sys.path 以允许 autodoc 相对于 docs 目录找到它们 (sys.path.insert(0, os.path.abspath('../../')))

  1. 关于失败的 numpy 导入:我有点困惑,因为它在一个自动记录的文件中得到了正确处理。那么,为什么只有三分之二的导入失败(它们在序言中都有相同的 import numpy as np 语句)?我花了几个小时寻找类似的问题,但只找到了有关 numpy 安装冲突的答案,我相信我没有。我该如何解决这个问题?

  2. 关于Mock报错,我试着按照https://github.com/seb-m/pyinotify/issues/110的思路,重新定义了几个mock函数,让它接受乘法运算:

class Mock(MagicMock):
    @classmethod
    def __getattr__(cls, name):
        return Mock()
    def __mul__(self, other):
        return Mock()
    def __rmul__(self, other):
        return Mock()
    def __pow__(self, other):
        return Mock()
    def __div__(self, other):
        return Mock()

没有任何效果。我可以通过将此操作放在 class 中或在需要的地方定义它来消除错误,但这很烦人,它定义了一个物理常量,该常量可能在整个模块的多个 classes/functions 中使用稍后的。如何让 mock 接受乘法?

如果这可能有帮助,这里是目录结构的相关部分:

--moduleroot/
  |--docs/
  |   |--requirements.txt
  |   |--Makefile
  |   |--make.bat
  |   |--source/
  |   |  |--conf.py
  |   |  |--rstfiles-for-doc
  |   |--build/
  |--module/
  |   |--__init__.py (probably useless?)
  |   |--Module1.py
  |   |--Module2.py
  |   |--Module3.py
  |--setup.py
  |--Manifest.in

提前谢谢你,在这一点上任何帮助将不胜感激,因为我不知道我做错了什么......(如果这太长,我很抱歉,因为我不知道出了什么问题我尽量提供尽可能多的相关信息)。

这解决了以下问题:

  • 使用 autodoc_mock_imports 配置变量指定要模拟的模块。

  • 当模拟 NumPy 时,np.pi 不起作用。 hbar_eV = h_eV/(2*np.pi) 是每次 Sphinx 运行时执行的模块级代码。要解决这个问题,请改用 math.pi