sdf3w
sdf3w

Reputation: 301

Keep getting incomprehensible error in this very simple cython program

Here's my very simple cython program.

test/__init__.py (Blank file)

test/__main__.py (Main file)

from test.program import Program
Program.Main([])

test/program.pyx

from .example import *
from .example cimport *

class Program:
    @staticmethod
    def Main(args):
        h = ExampleClass()
        h.SayHi()

test/example.pyx

cdef class ExampleClass:
    cdef SayHi(self):
        print("HI")

test/example.pxd

cdef class ExampleClass:
    cdef SayHi(self)

If I run this program by py36 test/__main__.py, program outputs this incomprehensible error..

Traceback (most recent call last):
  File "test\__main__.py", line 1, in <module>
    from test.program import Program
  File "test\program.pyx", line 1, in init test.program
    from .example import *
TypeError: Cannot overwrite C type ExampleClass

If I modify the code

from .example import *
from .example cimport *

to one of following code blocks

from .example import ExampleClass
from .example cimport *

or

from .example import *
from .example cimport ExampleClass

or

from .example import ExampleClass
from .example cimport ExampleClass

, the error disappears and program runs nicely without error.

I can't really understand why original unmodified code outputs weird TypeError: Cannot overwrite C Type ExampleClass.. Can someone please help me to understand the error and what the problem is?

Upvotes: 4

Views: 515

Answers (1)

danny
danny

Reputation: 5270

In program.pyx, both the Python module and Cython imports are used.

When the example.pyx code is compiled, ExampleClass has already been defined as a native type.

The python level import then instructs the python interpreter to load the python module containing ExampleClass native type - note, not the Cython definition of it but the runtime python module.

As that type had already been declared at compile time by Cython with a fixed definition, it is seen as an attempt to re-declare a native type. That is what TypeError: Cannot overwrite C type ExampleClass means.

In other words, the python level import is trying to re-declared a statically defined C extension class which is not allowed by Cython.

In short, remove from .example import <..> lines from .pyx files.

Python level imports are only needed when there are both Python only, as in a regular .py file, and Cython only declarations that both need to be used - that is not the case above.

As a side note, relative imports are not supported by Cython's cimport and also best not to use * for imports. The relative cimport code will break when installed as a package.

Upvotes: 1

Related Questions