如何在readthedocs上记录cython函数

时间:2012-11-05 19:12:02

标签: python cython python-sphinx

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

谢谢!

2 个答案:

答案 0 :(得分:13)

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

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

稍微长一点的答案和示例项目见下文。

有什么问题?

据我了解,sphinx会导入项目中所有需要记录的模块,然后在python中提取文档字符串。这对于Cython模块来说是失败的,因为它们无法直接导入并且必须先编译。编译模块在readthedocs上没有开箱即用,但它们提供了实现这一目标的工具。

如何解决这个问题。

在virtualenv中安装项目时,将构建Cython模块(转换为.so文件),然后可以导入。这可能需要一些外部模块(如下例所示,当然还有Cython)。这些可以在必须位于您的存储库中的pip requirements filerequirements.txt)中指定。

  1. Admin - >>下启用选项install your project inside a virtualenv readthedocs上的高级设置
  2. 输入requirements.txt相对于项目根目录的路径(以下示例中为docs/requirements.txt
  3. (如有必要,请更改python解释器版本)
  4. 现在每次构建文档时都会安装(使用python setup.py install)项目。如果单击readthedocs上 Builds 选项卡中的相应构建,则可以在 Setup Output 下看到安装脚本的输出。这是编译时错误可能出现的地方。请注意,编译项目可能需要一些时间。

    示例项目

    一个Python包,由几个Cython模块组成,每个模块都有Google-style 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
    

    requirements.txt

    cython>=0.20
    numpy>=1.9
    

    买者(S)

    在我的项目上尝试这个时,我遇到了无法导入我的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
    ...
    
    按照建议here

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

    要解决此问题,请完全删除该行。

    我希望这会有所帮助。

答案 1 :(得分:0)

You can mock out the modules that depend on C extensions将以下代码段添加到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()