Reputation: 549
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'
Upvotes: 3
Views: 995
Reputation: 549
To get main.py working, I had to:
Thou I have no Idea why it does not work when setup.py is inside myPackage!
myProject
│
├── main.py
├── setup.py
│
├── myPackage
│ ├── animal.pxd
│ ├── animal.pyx
│ ├── zoo.pxd
│ ├── zoo.pyx
and the setup.py
from setuptools import setup, find_packages, Extension
from Cython.Build import cythonize
extensions = [
Extension("myPackage.animal", ["myPackage/animal.pyx"]),
Extension("myPackage.zoo", ["myPackage/zoo.pyx"])]
compiler_directives = {"language_level": 3, "embedsignature": True}
extensions = cythonize(extensions, compiler_directives=compiler_directives)
Upvotes: 2