ImportError in Cython

2019-08-17 04:55发布

问题:

I'm fairly new to cython, so I have a basic question. I'm trying to import a base class from one cython file into another cython file to define a derived class. I have the following code in a single directory called cythonTest/:

afile.pxd
afile.pyx
bfile.pxd
bfile.pyx
__init__.py
setup.py

afile.pxd:

cdef class A:
    pass

afile.pyx:

cdef class A:
    def __init__(self):
        print("A__init__()")

bfile.pxd:

from afile cimport A

cdef class B(A):
    pass

bfile.pyx:

cdef class B(A):
    def __init__(self):
        print "B.__init__()"

setup.py:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

extensions = [Extension("afile", ["afile.pyx"]), 
              Extension("bfile", ["bfile.pyx"])]

setup(ext_modules=cythonize(extensions))

This code seems to compile correctly. Running import afile works fine, but running import bfile results in the following error

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "bfile.pyx", line 1, in init cythonTest.bfile
    cdef class B(A):
ImportError: No module named cythonTest.afile

Does anybody know what I'm doing wrong? I'm using Python 2.7.6 and Cython 0.27.3

回答1:

One solution is to use explicit import. The minus side: you must install the package for it to work.

I have the following structure:

.
├── cythonTest
│   ├── afile.pxd
│   ├── afile.pyx
│   ├── bfile.pxd
│   ├── bfile.pyx
│   └── __init__.py
└── setup.py

The files:

cythonTest/afile.pxd

cdef class A:
    pass

cythonTest/afile.pyx

cdef class A:
    def __init__(self):
        print("A__init__()")

cythonTest/bfile.pxd

cimport cythonTest.afile

cdef class B(cythonTest.afile.A):
    pass

cythonTest/bfile.pyx

cimport cythonTest.afile

cdef class B(cythonTest.afile.A):
    def __init__(self):
        print "B.__init__()"

The init file is empty, it is only used to define the directory as a module.

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

extensions = [Extension("cythonTest.afile", ["cythonTest/afile.pyx"]), 
              Extension("cythonTest.bfile", ["cythonTest/bfile.pyx"])]

setup(
    packages=['cythonTest'],
    ext_modules=cythonize(extensions),
)


回答2:

You seem to be using cythonTest as a package name (directory containing __init__.py used as a package).

The module name needs to be reflected in the extension names for importing to work correctly:

extensions = [Extension("cythonTest.afile", ["cythonTest/afile.pyx"]), 
              Extension("cythonTest.bfile", ["cythonTest/bfile.pyx"])]

Will also probably need to move the pyx files under the package directory - Cython uses the package name when building the extensions.