I'm writing a Cython 0.23 program, and I can't figure out how to use a cdef class
that I import from a different module in a type declaration. Here is a snippet that reproduces the problem.
test.py
:
import pyximport
pyximport.install()
from mymodule import *
obj = MyClass(42)
print(obj.field)
print(identity(obj).field)
This works as expected and prints 42
twice:
mymodule.pyx
:
cdef class MyClass:
cdef readonly int field
def __init__(self, field):
self.field = field
cpdef MyClass identity(MyClass obj):
return obj
This fails with a compiler error:
mymodule.pyx
:
from utils import MyClass
cpdef MyClass identity(MyClass obj):
return obj
utils.pyx
:
cdef class MyClass:
cdef readonly int field
def __init__(self, field):
self.field = field
The error:
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):
^
------------------------------------------------------------
The project I need this for is small and I can refactor it so that I don't need to import the class, but this solution doesn't look very clean. Is there a better way?
You need to use a declaration ".pxd" file and cimport
. (Essentially, cimport
happens at compile time, while import
happens at run time so Cython can't make use of anything imported).
Create "utils.pxd":
cdef class MyClass:
cdef readonly int field
"utils.pyx" now reads
cdef class MyClass:
def __init__(self, field):
self.field = field
(i.e. remove the declaration of field
since it's specified in the .pxd file).
Then in mymodule.pyx
from utils cimport MyClass
# other code follows...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With