我正在写一个Cython 0.23程序,我无法弄清楚如何使用cdef class我从类型声明中的不同模块导入的程序.这是一个重现问题的片段.
test.py:
import pyximport
pyximport.install()
from mymodule import *
obj = MyClass(42)
print(obj.field)
print(identity(obj).field)
Run Code Online (Sandbox Code Playgroud)
这按预期工作并打印42两次:
mymodule.pyx:
cdef class MyClass:
cdef readonly int field
def __init__(self, field):
self.field = field
cpdef MyClass identity(MyClass obj):
return obj
Run Code Online (Sandbox Code Playgroud)
这会因编译器错误而失败:
mymodule.pyx:
from utils import MyClass
cpdef MyClass identity(MyClass obj):
return obj
Run Code Online (Sandbox Code Playgroud)
utils.pyx:
cdef class MyClass:
cdef readonly int field
def __init__(self, field):
self.field = field
Run Code Online (Sandbox Code Playgroud)
错误:
Error compiling Cython file:
------------------------------------------------------------
...
from utils import MyClass
cpdef MyClass identity(MyClass obj):
^
------------------------------------------------------------
mymodule.pyx:3:6: 'MyClass' is not a type identifier
Error compiling Cython file:
------------------------------------------------------------
...
from utils import MyClass
cpdef MyClass identity(MyClass obj):
^
------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
我需要的项目很小,我可以重构它,这样我就不需要导入类了,但是这个解决方案看起来不太干净.有没有更好的办法?
您需要使用声明“ .pxd”文件和cimport。(本质上,这cimport发生在编译时,而import发生在运行时,因此Cython无法使用任何导入的东西)。
创建“ utils.pxd”:
cdef class MyClass:
cdef readonly int field
Run Code Online (Sandbox Code Playgroud)
“ utils.pyx”现在显示为
cdef class MyClass:
def __init__(self, field):
self.field = field
Run Code Online (Sandbox Code Playgroud)
(即删除声明,field因为它是在.pxd文件中指定的)。
然后在 mymodule.pyx
from utils cimport MyClass
# other code follows...
Run Code Online (Sandbox Code Playgroud)