2014-10-17 54 views
2

有兩個與導入有關的問題,可能與cython相關或可能不相關?導入文件和方法的Python/Cython問題

我有以下簡化文件來重新創建問題。所有文件都在同一個目錄中。 .pyx文件已成功編譯爲*.so*.pyc*.c文件。

setup.py:

from distutils.core import setup 
from Cython.Build import cythonize 

setup(
    ext_modules=cythonize("*.pyx"), 
) 

cy1.pyx:(用Cython)

cdef int timestwo(int x): 
    return x * 2 

cy1.pxd:

cdef int timestwo(int x) 

cy3.py:(正常蟒)

def tripleit(x): 
    return x*3 

go.py:

from cy1 import timestwo 
print str(timestwo(5)) 

給我的錯誤:導入錯誤:無法導入名稱timestwo

,如果我將其更改爲:

go.py:

import pyximport; pyximport.install() 
import cy1 
print str(cy1.timestwo(5)) 

它告訴我:AttributeError:'模塊'對象沒有屬性'timestwo'

如果我取出用Cython一起,並嘗試使用普通的Python的呼叫從cy3.py:

go.py:

import cy3 
print str(cy3.tripeleit(3)) 

我得到:AttributeError的: '模塊' 對象有沒有屬性 'tripeleit'

和最後如果我這樣做:

go.py:

from cy3 import tripleit 
print str(tripeleit(3)) 

我得到:

NameError: name 'tripeleit' is not defined 

對不起,如果這是超基本的,但我似乎無法弄清楚。

+0

你試過下面的答案嗎? – 2014-10-17 20:02:43

回答

5

的問題是,在go.py

from cy1 import timestwo 
print str(timestwo(5)) 

你想導入一個定義爲cdef的函數。

要將此函數暴露給Python,您必須使用defcpdef。可能你必須保留爲cdef,以便從其他Cython文件中獲得cimport,證明爲什麼你還有pxd文件。在這種情況下,我通常有一個類似於C的函數和一個可以從Python調用的包裝器。

在這種情況下,您cy1.pyx文件看起來像:

cdef int ctimestwo(int x): 
    return x * 2 

def timestwo(x): # <-- small wrapper to expose ctimestwo() to Python 
    return ctimestwo(x) 

和你cy1.pxd文件:

cdef int ctimestwo(int x) 

,這樣你可以cimport只有ctimestwo功能。

+1

謝謝Saullo這幫了我很多。這正是我需要做的。此外,對於後來發現此問題的人來說,如果ipython筆記本發生更改,則可能會遇到問題。 %reload_ext cythonmagic似乎並不總能奏效,但重新啓動內核幫助了我。 – omgwot 2014-10-18 15:16:24

+1

該解決方案殺死了cython – 2015-11-21 12:47:45

+0

@ DavoudTaghawi-Nejad的所有速度優勢其實並非如此。我只是包裝一個功能,以揭露它。但函數本身很快,所以將是包裝...你的downvote是不合理的 – 2015-11-21 13:32:40

1

關於你提到的第二個錯誤,你有一個錯字:

print str(tripeleit(3)) 

它應該是:

print str(tripleit(3)) 
+0

謝謝你avi你是絕對正確的。我認爲對於我的其他問題,它與pyx和pxd中的cdef和cpdef之間的區別有關。我想我必須將函數定義爲cpdef,如果它們能夠從python代碼中調用,但我仍然有點模糊,因爲它看起來像所有的文檔都指向將這些方法定義爲cdef,並且我讀取的是性能與cpdef問題,所以也許有人可以澄清? – omgwot 2014-10-17 05:19:45