Reputation: 31216
How does one import a compiled cython file in a pycharm python file?
Here is my setup.
From my project root directory, the cython class is "/classes/knn.cpython-35m-x86_64-linux-gnu.so." My python file is "/classes/testing_cython_knn.py."
I have an "__init __.py" file in "/classes/"...
However, Pycharm does not recognize the ".so" file as a file which I can import. What do I need to do in order to make this file available to import, so I can test it?
Currently, I have successfully compiled and imported a "helloworld.so" file in regular, terminal-based python...however, the function I defined was a pythonic function...no C-stuff.
My Cythonic file is:
import numpy as np
cimport numpy as np
from scipy.stats import mode
from scipy.spatial.distance import cdist
from threading import Thread
cdef class KNN:
cdef public int k
cdef public str metric
cdef public np.ndarray trainingX
cdef public np.ndarray trainingY
cdef public np.ndarray predict(self,np.ndarray X):
cdef np.ndarray distances,predicted_classes,sorted_distance_indices
distances = cdist(X,self.trainingX,metric=self.metric)
predicted_classes = np.zeros(X.shape[0],dtype=np.float64)
sorted_distance_indices = np.argpartition(distances,self.k,axis=1)[:,:self.k]
predicted_classes,_ = mode(self.trainingY[sorted_distance_indices])
return predicted_classes
And setup.py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
import numpy
extensions = [
Extension("knn",["cKNN.pyx"]),
Extension("*",["*.pyx"],include_dirs=[numpy.get_include()])]
setup(ext_modules = cythonize(extensions),include_dirs=[numpy.get_include()])
Currently, this fails on import to python running on the terminal with an Import Error:
Dynamic module does not define module export function (PyInit_knn)
Upvotes: 1
Views: 3191
Reputation: 321
The first thing I notice is that you are renaming your extension. For Cython, the name of the extension must correspond with the name of the file to compile. That should fix the
Dynamic module does not define module export function (PyInit_knn)
Second, you are declaring two extensions, but you have only one file (wich needs Numpy) so you should either remove the first extension completely (the * will take care of all the .pyx files in the folder) or remove the second and integrate the 'include_dirs' directive to the first extension, so you should change your extensions list to:
extensions = [
Extension("cKNN",["cKNN.pyx"],include_dirs=[numpy.get_include()])]
If you use --inplace or if you move the .so file to the right place, it will be imported. Pycharm has nothing to do there, it is all up to Cpython, but, in your setup.py, you have to be careful about setting the paths properly. If your project's folder structure is like:
- knnProject (this opens in Pycharm)
- - knnextension
- - - classes
- - - - __init__.py
- - - - cKNN.pyx
- - - __init__.py (this is required to do module import from /classes)
- - setup.py
- - test.py
Your extension should say:
extensions = [
Extension("knnextension/classes/cKNN",["knnextension/classes/cKNN.pyx"],include_dirs=[numpy.get_include()])]
The shared library file (.so or .pyd) will show up (by using --inplace) inside /classes. In the classes/__init__.py
file you can import the class with:
from .cKNN import KNN
and then from test.py:
from knnextension.classes import KNN
Check other working cython extensions, like my own, to see how the structure might be (that one uses Numpy too).
Upvotes: 3