2012-04-07 49 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 
    ...