2012-04-07 87 views
12

我最近通过将所有模块(顶级__init__.py除外)重命名为*.pyx,并将ext_modules = [Extension('foo', ['foo.pyx'])]放入setup.py来对我的项目进行Cython化。建设和安装工作正常。但是,当我做cd doc; make html时,狮身人面像失败,因为它不能导入任何现在是*.pyx的模块。如何在Cython上使用Sphinx?

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

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

我一直没能在网上找到任何有关使用Sphinx和Cython的信息。我查看了一些使用两者的项目的源代码,但他们似乎没有使用*.pyx文件中的文档字符串。我知道贤者会这样做,但那个项目对我来说太复杂了。

Sphinx是否支持Cython文件中的文档?如果是这样,我该如何做这项工作?

回答

4

随时留下一个更好的答案,但这里是我找到的修复。

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

但是,error while formatting arguments问题仍然存在。首先,您需要指示Cython将方法/功能签名嵌入到*.so文件中。通过设置embedsignature Cython指令来执行此操作。 dipy项目在每个*.pyx文件中设置此项,但也可以将其设置为setup.py(请参阅Cython文档以了解如何执行此操作)。尽管如此,这仍然不会将方法签名放入Sphinx文档中!有一个错误报告和修补方法签名问题here。截至目前(1.1.3),它仍然没有包含在最新的Sphinx版本中,但是如果你从开发回购安装Sphinx,它将会起作用。

6

你看起来有点混乱。狮身人面像并不是一个真正的语法分析器。您的Python代码必须可以运行,以使Sphinx能够捕获文档字符串。这就是为什么将扩展名文件重命名为“.py”没有帮助。

最近,我一直在与Sphinx和Cython合作,并且希望分享我的经验......下面是完整的详细过程,以便从docstrings中为给定的编译Cython扩展自动生成html文档:

[注:我使用的狮身人面像1.1.3和用Cython 0.17.4]

首先,使用Python的“文档字符串”(所有的限制也多了 - 通过例如,你无法用语言形容一个构造函数。见docstrings规格)在用Cython代码:

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”已被编辑告诉狮身人面像被找到你的模块:

# 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”文件已被修改,以及分辨哪个模块可能分析:

$ make html 

这是足以让我:

Contents: 

.. toctree:: 
    :maxdepth: 2 


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

最后通过做建设的文件(我在“.../_ build/html /”目录下得到了一组html文件)。自从上一个问题被问到后,可能是Sphinx和Cython已经发展了,但我没有处理“签名”问题。没有特定的Cython指令使用,也没有任何修正适用于狮身人面像...

希望这会有所帮助。

编辑:好吧,我想回我的话。我遇到了这个问题,“丹”在使用Epydoc时提到了关于“embedignature”的问题(所以我想这也是Sphinx的一个问题)。激活此编译器指令不发送蟒符合签名反正:

PyLabNode.SetNetwork(self, PyLabNetwork net) 

这有2个缺点:对于类的前缀和输入参数的点号。

最后,我能想出发送正确的人的唯一办法是在文档字符串的,像这样的第一行写一个兼容的签名:

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 

希望这可以帮助两个狮身人面像和epydoc的用户...


编辑:关于__cinit__,我能够与Epidoc成功生成的文档(不与狮身人面像试试)被描述加倍,像这样:

# 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 
+0

关于狮身人面像,PARAM应类文档中进行记录,而不是在构造函数,所以它在生成的文档中看起来不错。 – 2014-10-01 09:30:41

0

由于Golgauth解释说,狮身人面像的车博士模块需要从.so,而不是.pyx文档字符串。没有cythonizing一个Python模块时,不必进行任何更改到您的狮身人面像的配置产生你的文档的最简单的方法就是简单的构建扩展模块就位之前生成的文档:

python setup.py build_ext --inplace 

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

为了不运行sphinx-build前风险忘记这一步,你可以编辑sphinx-quickstart产生构建扩展模块Makefile

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