I am creating a cython package where several modules share extension types with each other. However I have problems getting the cimports right.
I have created a simple example project to show case my problem. As you can see: All cython files are within a package call myPackage.
myProject │ ├── main.py │ ├── myPackage │ ├── animal.pxd │ ├── animal.pyx │ ├── zoo.pxd │ ├── zoo.pyx │ ├── setup.py Can you explain to me, how to use cimport such that zoo.pyx has knowledge about the extension types in animal.pyx ?
This is the animal.pyx file ...
cdef class Animal: def __init__(self, str name, double weight): self.name = name self.weight = weight This is the animal.pxd file ...
cdef class Animal: cdef: public str name public double weight This is the zoo.pyx file ...
from myPackage.animal cimport Animal cdef class Zoo: def __init__(self): self.animals_cage = [] print('ready!') cpdef void add_animal(self, Animal animal): self.animals_cage.append(animal) This is the zoo.pxd file ...
from myPackage.animal cimport Animal cdef class Zoo: cdef list animals_cage cpdef void add_animal(self, Animal animal) The setup is done by ...
from distutils.core import setup, Extension from Cython.Build import cythonize ext_modules = [Extension(name="animal", sources=["animal.pyx"]), Extension(name="zoo", sources=["zoo.pyx"])] setup(ext_modules=cythonize(ext_modules)) The main.py is as basic as it can get ...
from myPackage.animal import Animal from myPackage.zoo import Zoo if __name__ == '__main__': a = Animal("bob", 4) z = Zoo() Trials and Results:
1st Trail:
Run setup.py inside myPackage. Run main.
compiling failed 'Animal' is not a type identifier (my guess) cython could not find myPackage.animal.pyx
2nd Trial:
Add include_path=['myPackage'] to cythonize call. Run setup.py inside myPackage. Run main.py
compiling works but main.py produces: AttributeError: 'zoo.Zoo' object has no attribute 'cage' 3rd Trial
make all cimports relative ( aka. from animal cimport Animal) and remove include_dirs from setup.py
compiling works and main.py works However, if you switch the imports in main.py. Making Zoo the 1st import:
from myPackage.zoo import Zoo from myPackage.animal import Animal if __name__ == '__main__': a = Animal("bob", 4) z = Zoo() ModuleNotFoundError: No module named 'animal'