0

I'm pretty new to cython and quite confused by the differences between cimport and import, they do not seem to behave the same way.

I have a cython project that contains two different cython modules:

test_cython
+ test
| + __init__.py
| + bar.pxd
| + bar.pyx
| + foo.pyx
+ setup.py

init.py

from .foo import *

bar.pxd

cdef class Bar:
    cdef get_name(self)

bar.pyx

cdef class Bar:
    cdef get_name(self):
        return "Hello from Bar"

foo.pyx

from .bar cimport Bar

def hello():
    return Bar().get_name()

setup.py

from setuptools import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [
    Extension('test.foo', ['test/foo.pyx']),
    Extension('test.bar', ['test/bar.pyx']),
]

setup(
    name='Test',
    ext_modules=ext_modules,
    include_dirs=["test"],
    cmdclass={'build_ext': build_ext},
)

I run my test code with this:

>>> import test
>>> test.hello()
'Hello from bar'

When I compile and run this project, everything works fine. But if I then try to use it as a submodule of another project by copying test to a python project like otherProject, and then running

>>> from otherProject import test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\path\to\otherProject\test\__init__.py", line 1, in <module>
    from .foo import *
  File "test\foo.pyx", line 1, in init test.foo
ModuleNotFoundError: No module named 'test.bar'

This was working when having only one cython module, so it seems to be related to cimport. It is also working when using the same pattern with pure python packages. My guess is that since the package needs to be fully qualified, the relative import doesn't really work, and test.bar cannot be a subpackage.

I'm trying to see if there could be a way to build the cython modules without them being fully qualified, but the multiple posts I've seen about this require the cython modules to be fully qualified.

For instance: Cython: ImportError: No module named 'myModule': how to call a cython module containing a cimport to another cython nodule?

pvallet
  • 177
  • 1
  • 15
  • If you use relative import, your cython-code should be probably cythonized with language_level=3, see https://stackoverflow.com/q/54900723/5769463 – ead Jun 23 '21 at 09:21
  • Yeah I also tried with this, but it doesn't change anything – pvallet Jun 23 '21 at 12:01
  • When you write an extension class methods declared as `cdef` will only be accessible by Cython code. You need to either use regular `def` (always slower, Python calls) or `cpdef` (slower Python calls if called from Python, faster C calls if called from Cython). – Oppen Jun 30 '21 at 00:16
  • Relevant docs: https://cython.readthedocs.io/en/latest/src/tutorial/cdef_classes.html – Oppen Jun 30 '21 at 00:16

0 Answers0