12

ReadTheDocs我不允许编译cython扩展,是否可以进行配置sphinx以便从cython文件中提取文档字符串而不实际编译它们?

谢谢!

4

2 回答 2

19

我遇到了同样的问题,发现现在可以在 readthedocs 上编译 Cython 扩展。

简短回答:可以使用 readthedocs 提供的 virtualenv 功能编译 Cython 模块。

有关稍长的答案和示例项目,请参见下文。

问题是什么?

据我了解,sphinx 导入项目的所有模块,这些模块应记录在案,然后在 python 中提取文档字符串。Cython 模块失败,因为它们不能直接导入,必须先编译。在 readthedocs 上编译模块不能开箱即用,但它们提供了一个工具来实现这一点。

如何解决这个问题。

在 virtualenv 中安装项目时,将构建 Cython 模块(到 .so 文件中),然后可以导入。不过,这可能需要一些外部模块(下面的示例为 numpy,当然还有 Cython)。这些可以在您的存储库中的pip 需求文件( ) 中指定。requirements.txt

  1. 在 readthedocs 上的Admin -> Advanced Settingsinstall your project inside a virtualenv下启用该选项
  2. 输入requirements.txt相对于项目根目录的路径(docs/requirements.txt在下面的示例中)
  3. (如有必要更改 python 解释器版本)

现在,您的项目将在python setup.py install每次构建文档时安装(使用)。如果单击readthedocs 上的Builds选项卡中的相应构建,则可以在Setup Output下看到 setup 脚本的输出。这是编译时错误可能出现的地方。请注意,编译您的项目可能需要一些时间。

示例项目

由几个 Cython 模块组成的 Python 包,每个模块都有Google 风格的 docstrings

my_project/
    setup.py
    my_package/
        __init__.py   # imports Cython modules
        cython_module1.pyx
        cython_module2.pyx
        ...
    docs/
        requirements.txt
        Makefile
        source/
            conf.py
            index.rst
            ... #  more documentation

要求.txt

cython>=0.20
numpy>=1.9

警告

在我的项目上尝试这个时,我遇到了我的 Cython 模块无法导入的问题。sphinx 的错误信息如下:

home/docs/checkouts/readthedocs.org/user_builds/... :4: WARNING: autodoc: failed to import module 'cython_module1';...
File "/home/docs/checkouts/readthedocs.org/user_builds/.../__init__.py", ...
from .cython_module1 import CythonClass

这发生了,因为我曾经在本地构建我的文档并添加了一行

...
sys.path.insert(0, os.path.abspath('../../')) # path to my_package
...

按照这里conf.py的建议给我。这解决了我在本地构建时的问题(我使用 编译我的项目),但是在 virtualenv 中安装时,这指向了 my_package 的错误版本(即源代码,而不是安装的包)。sphinx 找不到任何要导入的 .so 文件。python setup.py build_ext --inplace

要解决这个问题,只需完全删除该行。

我希望这有帮助。

于 2015-08-07T15:59:37.667 回答
0

您可以通过将以下代码段添加到您的来模拟依赖于 C 扩展的模块conf.py

import sys

class Mock(object):
    def __init__(self, *args, **kwargs):
        pass

    def __call__(self, *args, **kwargs):
        return Mock()

    @classmethod
    def __getattr__(cls, name):
        if name in ('__file__', '__path__'):
            return '/dev/null'
        elif name[0] == name[0].upper():
            mockType = type(name, (), {})
            mockType.__module__ = __name__
            return mockType
        else:
            return Mock()

MOCK_MODULES = ['pygtk', 'gtk', 'gobject', 'argparse']
for mod_name in MOCK_MODULES:
    sys.modules[mod_name] = Mock()
于 2012-11-13T16:07:13.820 回答