Issues with Cython: compiled module not found when imported - python

I'm having some trouble with cython. I recently found out about it and decided to use it in a project, but for some reason I'm unable to import the module/function that I've just compiled.
Here is what my sum.pyx file looks like:
def add(x, y):
return x+y
And this is my setup.py file:
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules = cythonize('image_converter.pyx'))
When I run python setup.py build_ext --inplace, the output shows this error:
Compiling sum.pyx because it changed.
[1/1] Cythonizing sum.pyx
C:\Users\User-name\AppData\Local\Programs\Python\Python39\lib\site-packages\Cython\Compiler\Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: C:\Users\User-name\Documents\Cython\sum.pyx
tree = Parsing.p_module(s, pxd, full_module_name)
running build_ext
building 'sum' extension
error: Unable to find vcvarsall.bat
Only one file was created called sum.c, but I'm aware that there should be some .so file created in a new directory but I couldn't find any, so I just continued and created the test.py file to see if the cython file worked:
import sum
print(sum.add(5,6))
But if I run this I get the error:
ModuleNotFoundError: No module named 'sum'
I am using Python 3.9.7 and Visual Studio Code, and I'm using the g++ compiler (MSYS2).
Thanks in advance.

Related

How to compile a cython program to a standalone executable?

Say, I have the following cython module renamed_module.pyx. This module contains all my cython code which include C and Python functions. Normally in development below is how I compile and run renamed_module.pyx.
A python file called setup.py that calls cython to convert my pyx modules into C code.
Setup.py code:
from distutils.core import setup
from Cython.Build import cythonize
setup(
name="appname",
ext_modules=cythonize(['renamed_module.pyx', 'other1.pyx', 'other2.pyx', 'other3.pyx']),
language_level=3)
I have another python file called run_renamed_module.py with the following code:
run_renamed_module.py:
import renamed_module
import os
import sys
sys.path.insert(0, os.path.abspath("."))
renamed_module.startingfunction()
Finally I compile it as following which works perfectly: python Setup.py build_ext --inplace && python run_renamed_module.py
Question
Now, I would like to convert my renamed_module.pyx into a standalone executable or a *.exe file that would open my cython GUI App.
After doing some research, I was able to first convert my renamed_module.pyx code into C code using cython renamed_module.pyx --embed -o renamed_module_comp.c
and then compile it to a binary file using gcc -c -DMS_WIN64 -shared -pthread -Wall -IC:/Users/[username]/AppData/Local/Programs/Python/Python39/Include -LC:/Users/[username]/AppData/Local/Programs/Python\Python39\libs -o app.exe renamed_module_comp.c.
With these two steps, I fall into no errors and they compile just fine. But now when I attempt to execute app.exe, I get the following error:
This app can't run on your PC. To find a version for your PC, check with the software publisher.
As reported/commented by other developers on the web, app.exe seem to be a DLL file. So, I tried to copy app.exe into an external folder, open python terminal from that directory, and call import app. With that I get:
ImportError: DLL load failed while importing app: %1 is not a valid Win32 application.
Unfortunately I don't know where to go from here. Any direction is really appreciated.
OS: Windows 10 x64
Python Version: Python 3.9.1
Cython Version: Cython version 0.29.23
GCC Version: gcc.exe (GCC) 9.2.0
GUI Libs: PyQT5 - Tkinter and pysimplegui
Summary of the question: I basically, want to compile my cython GUI app into a standalone executable program.

Cython does not build .so file

I'm trying cython for the first time. Here is what I have.
setup.py
import os
from distutils.core import setup
from Cython.Build import cythonize
os.chdir(os.path.dirname(__file__))
setup(ext_modules = cythonize('example123.pyx'))
example123.pyx
def say_hello(name):
print(f"Hello {name}")
After setup.py build_ext --inplace I only see example123.c in the folder, no other files created. Searching through all the files didn't provide any results. As far as I know, a .so or .pyd file must have appeared to import into a python script. What may be the problem?
My specs: Windows 7 x64, gcc mingw64, python 3.8, cython 0.29.24

Cython/Python comparison invalid syntax error

I would like to compare Python with Cython in term of time execution, so I wrote two files:
fac.py
def factorial(n):
if n >= 1:
return n*factorial(n - 1)
return 1
fastfac.pyx
cpdef long fastfactorial(long n):
if n>= 1:
return n*fastfactorial(n - 1)
return 1
Then I wrote a setup file:
setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules = cythonize('fastfac.pyx'))
From the Powershell I executed the two commands:
pip install Cython
python setup.py build_ext --inplace
From the second command I get the following message:
Compiling fastfac.pyx because it changed.
[1/1] Cythonizing fastfac.pyx
C:\Users\.....\venv\lib\site-packages\Cython\Compiler\Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: C:\Users\.....\fastfac.pyx
tree = Parsing.p_module(s, pxd, full_module_name)
running build_ext
building 'fastfac' extension
error: Unable to find vcvarsall.bat
However I tried to make a comparison, so I wrote the file:
comparison.py
from fastfac import fastfactorial
from fac import factorial
from timeit import timeit
print(timeit('fastfactorial(20)', globals = globals(), number = 10000))
print(timeit('factorial(20)', globals = globals(), number = 10000))
When I run it, I get this error message:
Traceback (most recent call last):
File "C:/Users/...../comparison.py", line 1, in <module>
from fastfac import fastfactorial
ModuleNotFoundError: No module named 'fastfac'
It seems that in the file python.pyx the definition cpdef long fastfactorial(long n) is not recognized as a regular function definition but as a syntax error; in fact, if I try to run that file I get the error message:
File "C:/Users/...../fastfac.pyx", line 1
cpdef long fastfactorial(long n):
^
SyntaxError: invalid syntax
How can I solve? How can I correctly define a cpdef inside a .pyx file?
what am I missing?
The problem is not your definition of fastfactorial, it is the fact that your setup.py exited with an error and, presumably, without compiling fastfac into a c library. In general, you should always fix such errors.
Your error appears to be happening because you don't have a Microsoft Visual C++ compiler installed. You can follow the instructions in this answer to choose a version of Visual C++ to install.
You also have a warning about the language_level not being set. You shouldn't ignore warnings either so it is worth explicitly stating the level in your setup.py.
setup(ext_modules=cythonize('fastfac.pyx'), language_level=3)

Pandas with py2exe: ImportError: C extension: dist not built

Trying to build a py2exe (0.6.9) package, the module has a dependency that uses pandas (0.16.2).
When "py2exe'ing", no errors are shown and the pandas python package is within the py2exe package.
When trying to run the .exe, it fails with:
File "pandas__init__.pyo", line 13, in
ImportError: C extension: dist not built. If you want to import pandas from the source directory, you may need to run 'python setup.py build_ext --inplace' to build the C extensions first.
I tried building pandas with that suggested command option, and then built a wheel from it, but didn't change the result.
What else could I be missing?
Update: This is not a fix to the problem, but if for anyone is also possible, I can confirm that changing to PyInstaller was a workaround.

Cython module doesn't work

I'm trying to produce a simple fibonacci algorithm with Cython.
I have fib.pyx:
def fib(int n):
cdef int i
cdef double a=0.0, b=1.0
for i in range(n):
a, b = a + b, a
return a
and setup.py in the same folder:
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize('fib.pyx'))
Then I open cmd and cd my way to this folder and build the code with (I have [http://www.microsoft.com/en-us/download/details.aspx?id=44266](this compiler) :
python setup.py build
Which produces this result:
C:\Users\MyUserName\Documents\Python Scripts\Cython>python setup.py build
Compiling fib.pyx because it changed.
Cythonizing fib.pyx
running build
running build_ext
building 'fib' extension
creating build
creating build\temp.win-amd64-2.7
creating build\temp.win-amd64-2.7\Release
C:\Anaconda\Scripts\gcc.bat -DMS_WIN64 -mdll -O -Wall -IC:\Anaconda\include -IC:
\Anaconda\PC -c fib.c -o build\temp.win-amd64-2.7\Release\fib.o
writing build\temp.win-amd64-2.7\Release\fib.def
creating build\lib.win-amd64-2.7
C:\Anaconda\Scripts\gcc.bat -DMS_WIN64 -shared -s build\temp.win-amd64-2.7\Relea
se\fib.o build\temp.win-amd64-2.7\Release\fib.def -LC:\Anaconda\libs -LC:\Anacon
da\PCbuild\amd64 -lpython27 -lmsvcr90 -o build\lib.win-amd64-2.7\fib.pyd
So it seems the compiling worked and I should be able to import this module with
import fib
ImportError: No module named fib
Where did I go wrong?
Edit:
os.getcwd()
Out[6]: 'C:\\Users\\MyUserName\\Documents\\Python Scripts\\Cython\\build\\temp.win-amd64-2.7\\Release'
In [7]: import fib
Traceback (most recent call last):
File "<ipython-input-7-6c0ab2f0a4e0>", line 1, in <module>
import fib
ImportError: No module named fib
The compiling worked however the library was placed under: build\lib.win-amd64-2.7 so you have to either copy/move the file in the current directory or change your current directory to that one.
You can see this in the last part of the command run:
-o build\lib.win-amd64-2.7\fib.pyd
The -o option stands for output and specifies where it should put the final compiled file.
Use
python setup.py build_ext --inplace
--inplace flag will put your pyd in the working directory

Categories

Resources