I am running Python 3.5 on Windows 10 and I would like to compile my Python code into a single executable to share with some end users. I'm using Cython 0.25.2 to try to get this done.
I've got a HelloWorld program working, by using the Cython --embed flag. From the Windows command prompt Cython makes a .c file:
# (myVirtualEnv) > cd (pathToSourceCode)
# (myVirtualEnv) > py (pathToVirtualEnv)\Scripts\cython.exe helloWorld.pyx --embed
This gives me a HelloWorld.c file. Then I open the MSVC++ 2015 x86 Native Command Prompt and compile the HelloWorld.c file into a Windows exe:
# > cd (pathToSourceCode)
# > cl.exe /nologo /Ox /MD /W3 /GS- /DNDEBUG -I(pathToVirtualEnv)\Include -I(pathToVirtualEnv)\PC /TchelloWorld.c /link /OUT:"helloTest.exe" /SUBSYSTEM:CONSOLE /MACHINE:X86 /LIBPATH:(pathToVirtualEnv)\Lib /LIBPATH:C:\Python35\libs
This works well. When run from the windows command prompt my new helloTest.exe program prints to the command line. I need to figure out how to get the 1st set of commands (from the regular command prompt) into a distutils setup script, which I haven't done. Perhaps I can make the windows compiler commands into a make file or batch file or something.
The shortcomings here are that I want to be able to build up many modules and packages together and I also don't want to ensure that the end user has all of the dependencies (Python 3.5 and all of the needed modules) in place.
I haven't been able to figure out how to build multiple Cython files and then link them into the final Windows .exe. However, seeing how I also want to include Python itself and any included python modules, I really need a freeze tool in addition to some pre-compilation processing.
Cython has a demo folder for cython_freeze. This looks perfect. It says it pulls all included modules, including Python itself, into one c file for compilation. The example file includes a readme and a make file for gcc. I don't fully understand what's going on here, and since I'm using MSCV cl.exe, I think the right thing to do is to find/ modify this to work for cl.exe. I lack the skills to do this. In fact, because I'm on windows I got cython from pre-compiled wheels and I'm not even sure if cython_freeze exists in my virtualenv (I did a search and didn't come up with anything). Similarly, "cython freeze" web searches also came up empty. Thus far I've got the cython --embed HelloWorld program working and I've downloaded the cython source from GitHub to review the cython_freeze readme and make files.
So, my questions:
- How can I use cython_freeze and cl.exe to build a single, windows executable that contains python, my main program and included packages/modules (standard or my custom ones)?
- Because I installed Cython 0.25.2 from a wheel pre-compiled for Windows, is cython_freeze even in my virtualenv already? If so, how do I use it? If not, how do I "install" it?
I'm definitely open to other non-cython_freeze ways of doing this. However, I should note that I've looked at several other options that didn't look nearly as promising:
- py2exe and cx-freeze and other similar freeze tools zip up the custom code but still require Python and all modules to be installed. This put too much on my users. I really want them to be able to click.exe and (as long as they are on Windows) have it run.
- I've considered using gcc as the compiler, but since MSVC 2015 is used to compile Python for windows and all of the extensions it sounds like this would open the door to lots of compatibility problems with python itself.
- I'm also leaning toward cython as I have some fairly slow "big math" routines in numpy that are taking too long, so I'm motivated to learn more about cython to speed those up soon too.
In addition to windows10 and Python 3.5, I'm using pip and virtualenv to manage my packages and create my virtualenv. I'm not using ant or conda. Cython, and most my other packages, are installed from pre-compiled wheels, as linked above.
UPDATE:
The spirit of my question is actually about packaging Python for users who don't have Python installed. Matt gives an excellent way to do that (and a good education on compiling Python). Biswa_9937 and S.Moncayo correctly point out that Py2Exe (Python versions 3.4 and earlier) and PyInstaller (works on Python 3.5) can also achieve this goal. These are great answers and very helpful.
However, the details of my question are about getting Cython_freeze to work on Windows. No one has attempted that, so I'm leaving the question unanswered in hopes that a Cython guru can weigh in.