【问题标题】:How do I use Sphinx with Cython?如何将 Sphinx 与 Cython 一起使用?
【发布时间】:2012-04-07 19:08:54
【问题描述】:

我最近通过将所有模块(顶级__init__.py 除外)重命名为*.pyx 并将ext_modules = [Extension('foo', ['foo.pyx'])] 放入setup.py 来对我的一个项目进行Cythonized。建筑和安装工作正常。但是,当我执行 cd doc; make html 时,Sphinx 会失败,因为它无法导入现在为 *.pyx 的任何模块。

如果我编辑doc/conf.py 并将sys.path.insert(0, os.path.abspath('..')) 更改为sys.path.insert(0, os.path.abspath('../build/temp.linux-x86_64-2.7')),那么Sphinx 可以找到所有模块并生成文档,但在这种情况下我会收到error while formatting arguments for foo.bar: <built-in function bar> is not a Python function 之类的错误。这大概是因为现在 Sphinx 只能访问 *.so 文件,而不是源文件。同样的sys.path 修改还允许通过Sphinx (make doctest) 运行文档测试。

我尝试的另一个解决方案是使用扩展名*.py 而不是*.pyx(并在setup.py 中使用ext_modules = [Extension('foo', ['foo.py'])])。在这种情况下,文档构建正确,但我认为 doctests 现在绕过 Cython。

我无法在网上找到有关同时使用 Sphinx 和 Cython 的任何信息。我查看了一些同时使用两者的项目的源代码,但它们似乎没有使用*.pyx 文件中的文档字符串。我知道 Sage 有,但那个项目太复杂了,我无法分清。

Sphinx 是否支持 Cython 文件中的文档字符串?如果是这样,我该如何进行这项工作?

【问题讨论】:

标签: cython python-sphinx


【解决方案1】:

你在这里看起来有点困惑。 Sphinx 并不是真正的句法分析器。您的 Python 代码必须可运行才能使 Sphinx 能够捕获文档字符串。这就是为什么将扩展文件重命名为“.py”没有帮助的原因。

好吧,我最近一直在使用 Sphinx 和 Cython,并想分享我的经验......这是从 docstrings 为给定的已编译 Cython 扩展自动生成 html 文档的完整详细过程:

[注意:我使用了 Sphinx 1.1.3 和 Cython 0.17.4]

首先,在 Cython 代码中使用 Python 的“文档字符串”(具有所有限制 - 例如,您无法描述构造函数。请参阅 docstrings 规范):

cdef class PyLabNode:
    """
    This is a LabNode !!!
    """
    cdef LabNode* thisptr
    cdef PyLabNetwork network

    def __cinit__(self):
       self.thisptr = new LabNode()

    def __dealloc__(self):
       if self.thisptr:
           del self.thisptr

    def SetNetwork(self, PyLabNetwork net):
        """
        Set the network !!!
        """
        self.network = net

并重新编译“yourextension.so”。

然后运行“sphinx-quickstart”并回答问题。当被问及“autodoc”时,不要忘记说是。这将生成“Makefile”、“index.rst”文件和“conf.py”文件。

必须编辑最后一个“conf.py”以告诉 Sphinx 找到您的模块:

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath('../../parent/dir/of/yourextension/'))

“index.rst”文件也必须进行编辑,以告知可以分析哪个模块:

Contents:

.. toctree::
   :maxdepth: 2


.. automodule:: yourextension
   :members:
   :undoc-members:
   :show-inheritance:

最后构建文档:

$ make html

这对我来说已经足够了(我在“.../_build/html/”目录中得到了一组 html 文件)。自从提出上一个问题以来,Sphinx 和 Cython 可能已经进化,但我没有要处理的“签名”问题。没有要使用的特定 Cython 指令,也没有适用于 Sphinx 的任何修复...

希望这会有所帮助。

编辑:好吧,我想收回我的话。我在使用 Epydoc 时遇到了“Dan”提到的关于“embedsignature”问题的问题(所以我想这也是 Sphinx 的问题)。激活此编译器指令无论如何都不会发送符合 python 的签名:

PyLabNode.SetNetwork(self, PyLabNetwork net)

这有两个缺点:类前缀和类型参数的点符号。

最后,我能想出发送正确签名的唯一方法是在文档字符串的第一行写一个合规签名,如下所示:

def SetNetwork(self, PyLabNetwork net):
    """
    SetNetwork(self, net)
    Set the net !!!
    @param self: Handler to this.
    @type self: L{PyLabNode}
    @param net: The network this node belongs to.
    @type net: L{PyLabNetwork}
    """
    self.network = net

希望这可以帮助 Sphinx 和 Epydoc 用户...


编辑:关于__cinit__,我能够通过将描述加倍使用Epidoc(没有尝试使用Sphinx)成功生成文档,如下所示:

# For Epydoc only (only used for docstring)
def __init__(self, sim):
    """
    __init__(self, sim)
    Constructor.
    @param sim: The simulator this binding is attached to.
    @type sim: L{PyLabSimulatorBase} 
    """ 

# Real Cython init
def __cinit__(self, PyLabSimulatorBase sim):
   self.thisptr = new LabNetBinding()
   self.sites = []
   simulator = sim

【讨论】:

  • 关于 Sphinx,param 应该记录在类文档中,而不是在构造函数中,因此在生成的文档中会很好看。
【解决方案2】:

请随意留下更好的答案,但这是我找到的解决方法。

dipy 项目手动从doc/conf.py 导入自己的模块。这需要先安装模块,但它会修复导入错误(并且 doctests 将在 Cythonized 文件上运行)。

但是,error while formatting arguments 问题仍然存在。首先,您需要指示 Cython 将方法/函数签名嵌入到 *.so 文件中。通过设置 embedsignature Cython 指令来做到这一点。 dipy 项目在每个 *.pyx 文件中设置它,但也可以在 setup.py 中设置它(有关如何执行此操作,请参阅 Cython 文档)。不过,这仍然没有将方法签名放入 Sphinx 文档中!有针对方法签名问题here 的错误报告和补丁。截至目前(1.1.3),它仍未包含在最新的 Sphinx 版本中,但如果您从开发存储库安装 Sphinx,它将可以工作。

【讨论】:

    【解决方案3】:

    正如 Golgauth 所解释的,Sphinx 的自动文档模块从 .so 获取文档字符串,而不是从 .pyx 获取文档字符串。在对 Python 模块进行 cythonize 时,无需对 Sphinx 配置进行任何更改即可生成文档的最简单方法是在生成文档之前就地简单地构建扩展模块:

    python setup.py build_ext --inplace
    

    这样,autodoc 将在常规 Python 模块旁边找到扩展模块,并能够按照您的预期生成文档。

    为避免忘记此步骤,您可以编辑由sphinx-quickstart 生成的Makefile 以在运行sphinx-build 之前构建扩展模块:

    html:
      @cd /path/to/setup.py; python setup.py build_ext --inplace
      ...
    

    【讨论】:

    • 你能解释一下吗?声明在Makefile 内部的什么位置?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-22
    • 2021-11-08
    • 2015-06-22
    • 2018-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多