How to create an executable python script with Cython and cx_freeze:

Setup:

This section will list, and provide links to, all the software required on the machine that will be “compiling” the python executable. I am assuming the machine anyone will try to duplicate this on has the following:

Here is what you will need in addition to the aforementioned:

cx_freeze and Cython should not give you any problems at installation, unless for some reason your version of Python is not in your PATH. Windows SDK may have an issue installing if you already have visual studios or another version of Windows SDK installed. In that case: you may check the version of visual studios/Windows SDK you have installed, and if it is not the appropriate version, you’ll most likely need to uninstall, then install the appropriate version of the Windows SDK. At the bottom are some links which may provide some useful information if the installation fails, or if you’d just like to know a little more about what I had to look at to figure out how to do this myself.

Compiling with Cython:

Cython will not create standalone executables of your python code. There is supposed to be a way to accomplish something like this with Cython, namely using the ‘--embed’ option, however this guide does not explore that option,(I was not successful in using this option, it may very well be worth looking into though, as then you should not need cx_freeze). Cython will however create compiled extensions/libraries that you can then call from a python script.

  1. Take any working,(and ideally debugged), python script and move/copy into a separate folder, we’ll call ‘my_folder’, as well as any modules you have wrote that your script depends upon.
  2. In your script/modules, you’ll need to break apart your code into functions and/or objects/methods. The code that is using all of your modules, i.e. the code which may be considered your ‘main’ program, should be wrapped up in a main function/method, that when called, will run all the desired code,(this may require a bit of work, as, you may need to change some variables to global variables in order for this to work, and then decide whether or not you want them to remain that way, and if not what changes you may need to make). In summary, by the end of this step, you should be able to run all of your code by calling a single function/method.
  3. Now you need to create a script called ‘cy_setup.py’,(or whatever, it just needs a ‘.py’ at the end), it should be in the same folder as your other python scripts. It should look something like this:

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

    my_scripts = (“my_main.py”, “some_one.py”, “some_body.py”, “some_where.py”)

    setup(ext_modules = cythonize(my_scripts))
    -------------------------------------------------------------------------------------------------------------------

    This is probably not the only way to do this, nor does this express the full functionality of the cython toolkit. If more information on Cython would be helpful, the website is linked at the bottom.
  4. Now open up the sdk command shell, you should be able to find it from the windows start menu under something like: All Programs -> Accessories -> Microsoft Windows SDK v7.1. In the shell you should now be in the folder where you installed the Windows SDK. From here enter the following commands,(after entering the second command the color of the text should change from yellow to green, if you haven’t done anything with your colors or screen):

               set DISTUTILS_USE_SDK=1
               setenv /x64 /release
  5. Now move,(via the ‘cd’ command, I’ll provide a link to a site with some basic Windows prompt commands at the bottom), to ‘my_folder’, which has all of your scripts and your ‘cy_setup.py’. Now type in the command:

               python cy_setup.py build_ext --inplace > comp_log.txt 2> err_log.txt

    the last bit, ‘> comp_log.txt 2> err_log.txt’, is optional, if you don’t do this,(a redirection), all the compile/error info will appear on the terminal, which just looks messy, and also, because the sdk command prompt will not hold a very large number of lines of text, depending on how much you are trying to compile, and the number of errors that pop up during the attempt, you may lose some information valuable to debugging if you don’t redirect that information into a file which you can open and read, in it’s entirety, at your leisure. You should notice a bunch of new files in your folder as well as a folder named ‘build’, which contains a subfolder, which contains a subfolder, which contains the stuff you just compiled, don’t move these files around, i.e. to different folders, I do not think you need most of them, but I have not tested how the next steps will work without all of them being where they are.

Creating the “executable” using cx_freeze:

  1. Assuming the previous steps,(have eventually), went well, you should now create a new python script in ‘my_folder’, which will import what is needed to call your main function/method, and then call it. All you need to do to import your extension(s) is to import the name of the module,(file name without the file extension,like ‘,py’, at the end).
  2. You should now create another python script in ‘my_folder’, named ‘cx_setup.py’,(or whatever). It should look something like this:
    -------------------------------------------------------------------------------------------------------------------
               from cx_Freeze import setup, Executable

               my_packages = [
                                           ‘compiled_mod_1’,
                                           ’compiled_mod_2’,
                                           ’other_mods’,
                                           ’gzip’,
                                           ’inspect’
                                          ]

               build_opt = {“packages” : my_packages}

               TARGET = Executable(
                                    script=”path\\my_main.py”,
                                    packages=my_packages,
                                    targetName=’my_executable.exe’,
                                    base =’Win32GUI’
                                   )
               setup(
                         name=”my_exe”,
                         version=”0.1”,
                         description=”Some executable that does something”
                         options={“build_exe” : build_opt}
                         executables=[TARGET]
                        )
    -------------------------------------------------------------------------------------------------------------------
    Some things you should be prepared to name in ‘packages’ here, which doesn’t make a whole lot of sense, are the following:
  1. ‘inspect’
  2. ‘gzip’
  3. modules from libraries not shipped with python, which your scripts use, such as ‘lxml’

Later you may need to come back to this and include more weird things, it all depends on what you’re scripts need to run, and how cx_freeze behaves for you.

  1. This last step can be somewhat frustrating and error-prone, as I believe cx_freeze has some issues which still have not been worked out very well, it seems to be inconsistent with importing modules it needs, I have also not found the documentation to be very helpful,(though perhaps with a little more digging through the source code and experimentation I could use cx_freeze in a way where it would work more reliably). You should now enter the following command,(I strongly suggest the redirection I include here):

               python cx_setup.py build > my_setup_log.txt 2> setup_err.txt

    Why use the redirection? You, as I have many times, may need to scour the error/setup log for errors, such as failed imports, which generally can be remedied by importing what cx_freeze would not into the script you made in step 7 through the packages, or include options.
  2. Assuming all has went well, there should be a new folder in your ‘build’ sub-folder named something like:

              exe.win-amd64

    which will contain an executable which you can now run by itself! Note, this executable will only work if it is in that folder it’s in now. The folder can be moved wherever, however, and you can even send a copy to anyone who has a compatible machine/system. They will be able to run your executable,(they don’t need python or any of the things you may have installed to create the executable). Now, it’s important to note that your are not done here, you need to run that executable and test
    all,(or as much as possible), the functionality it has. I’m not saying this just because it’s what a responsible and ‘good’ programmer would do, but in my experience, cx_freeze-made executables will have a lot of bugs related to failed imports, or failed dependencies within your scripts,(I mean that something simply wasn’t imported in one of your scripts where it should have been). The former may or may not be your fault,(again cx_freeze just doesn’t seem to import some things if it doesn’t feel like it when you happen to package with it), the best I can say for this is that you should go back to step 7 and include what your error message says is missing. The latter is almost certainly your fault,(why didn’t you debug your code?!), you need to make sure your code is internally stable and has what it needs and from the proper sources were it to run through the python interpreter,(anything which is ok for the python interpreter should be ok for Cython and cx_freeze).

Conclusion:

Hopefully this was sufficient to get you through the process. I can say with some certainty that any problems you have with Cython can be solved with, at most, a few google searches and a little digging. Though, cx_freeze may turn your hair gray, or just make it all fall out. So, why use it? Note: I really didn’t, and still don’t know much about it, it is open source though, so if you’d like, there is a link at the bottom to the source code on bitbucket, as well as it’s documentation. I’m sure with enough time and digging one could make cx_freeze behave as expected without changing it,(or simply have the correct expectations for what it can and cannot do). I just haven’t had the time to do this, and so will continue to be generally frustrated by it until I get around to doing aforementioned digging. Even though cx_freeze, in the right hands, may be the perfect tool for this kind of thing, perhaps it would be worth figuring out how to do it all through Cython. If you have any questions, comments, corrections, or concerns, please send me an e-mail at the address at the bottom.

Windows SDK/Cython Installation Info:

Cython website:

Windows prompt commands,(first one a list, second one just for ‘cd’):

cx_freeze source code:

cx_freeze documentation:

My e-mail:

c.lawrence.v@gmail.com