Python/Cython trouble importing files and methods

2019-05-19 01:14发布

问题:

There are 2 issues both relating to importing that may or may not be cython related?

I have the following simplified files to recreate the problem. All files are in the same directory. The .pyx files have successfully compiled into *.so, *.pyc and *.c files.

setup.py:

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

setup(
    ext_modules=cythonize("*.pyx"),
)

cy1.pyx: (cython)

cdef int timestwo(int x):
    return x * 2

cy1.pxd:

cdef int timestwo(int x)

cy3.py: (normal python)

def tripleit(x):
    return x*3

go.py:

from cy1 import timestwo
print str(timestwo(5))

Gives me the error: ImportError: cannot import name timestwo

if I change it to:

go.py:

import pyximport; pyximport.install()
import cy1
print str(cy1.timestwo(5))

it tells me: AttributeError: 'module' object has no attribute 'timestwo'

if I take out the cython all together and try to use normal python call from cy3.py:

go.py:

import cy3
print str(cy3.tripeleit(3))

I get: AttributeError: 'module' object has no attribute 'tripeleit'

and last if I do:

go.py:

from cy3 import tripleit
print str(tripeleit(3))

I get:

NameError: name 'tripeleit' is not defined

Sorry if this is super basic but I cannot seem to figure it out.

回答1:

The problem is that in go.py:

from cy1 import timestwo
print str(timestwo(5))

you are trying to import a function defined as cdef.

To expose this function to Python you have to either use def or cpdef. Possibly you have to keep as cdef in order to cimport from other Cython files, justifying why you also have the pxd file. In that case I usually have a C-like function and a wrapper that can be called from Python.

In this case your cy1.pyx file would look like:

cdef int ctimestwo(int x):
    return x * 2

def timestwo(x): # <-- small wrapper to expose ctimestwo() to Python
    return ctimestwo(x)

and your cy1.pxd file:

cdef int ctimestwo(int x)

such that you can cimport only the ctimestwo function.



回答2:

Regarding your second error, you have a typo:

print str(tripeleit(3))

It should be:

print str(tripleit(3))