The knockout guide to py2exe
To compile your python programs like a world champion.
Introduction
There’s a tough reality for some unlucky python developers: You must compile your program. Whether it is for one or thousands of clients, compiling is an extremely tedious task to achieve. There’s also a huge lack of documentation and a lot of disinformation in the web about basic issues you may face while compiling. But, once you get the hang of it, It’s no longer tedious, but you also find the joy in it (DISCLAIMER: If I were a professional boxer, I wouldn’t be writing this blogpost, so feel free to disagree). The same thing could be applied to boxing…

… Sort of. But yeah, you need a lot of practice, to get the hang of it in a lot of technical aspects that go beyond the objective (in boxing would be knocking your opponent out and in our case, compiling) but once you start assimilating all these things, you are ready to hit the ring. What I’m saying is: You came across to this guide with a problem and will be gone with a solution (and awesome boxing gifs).
This guide was tested on python 2.7 with py2exe 0.6.10a1 in a Windows 7 ultimate machine and I don’t know how It’s supposed to work on with another version in another environment. Don’t bother trying to do this on Linux, it won’t work.
The MSVCP90.dll problem
This issue is basic. It doesn’t matter who you are and what you’re compiling, the very first time you try to compile a python program you’ll see this in the console:
*** finding dlls needed ***
error: MSVCP90.dll: No such file or directory
And this problem is easy, but you’ll find several ways to fix it that changed throughout time, but the definite solution is as simple as walking on the ring:
- Download the Microsoft Visual C++ 2008 Redistributable Package and install it. This will also help you compile all the important files you need to make your python program work.
- Search for the MSVCP90.dll file. If it doesn’t appear on your computer, python-compiled programs like Sublime Text and Mercurial contain it.
- Paste the file in C:\Python27\DLLs.

And that’s it, now you’ll be floating like a butterfly and compiling like a beast.
The proper setup.py skeleton
I’ve seen around the web a lot of ways to make a setup.py that works with py2exe but most of them are just fragments that don’t make sense or have just the script they want to compile. This is an example of how a base setup.py should look like:
Now we’re ready to make ourselves some .exe files!
Just execute python setup.py py2exe.

“ImportError: no module named x” when compiling
So, you finally made your own setup.py and want to compile it, but when it’s creating it an import error appears and…

… knocks you out.
But the solution is easy. If you don’t use or need the module, just add this line:
‘ignores’:[‘ignored module’],
But if you need it and even though you added it to includes it still throws the error, add this line:
‘packages’:[‘your module’],
Sometimes being specific does help:
‘packages’:[‘module.submodule’],
Then go ahead and compile again and it should be long gone.
“ImportError: no module named x” when opening your .exe
You finally maded it! Your very own .py -> .exe and want to see how great it works. But… It doesn’t work. And the error is oddly, one import you don’t need and/or use in your entire program. You just need to create an array called mod_excludes:
mod_excludes = [
# The module you want to exclude
# Example:
‘pdb’
]
And then add this line after the includes option in the setup.py like this:
‘excludes’: mod_excludes,
All of this, of course, with proper indentation. Forgive medium, it does not support code yet. This is the array I use and find extremely useful for pretty much every .exe I do:
mod_excludes = [ “Tkinter”, “doctest”, “unittest”, “pydoc”, “pygments”, “pdb”, “_ssl”, “difflib”,]
Once this is done, try to run the compiler again and then when you execute your .exe file this error should be gone. If not, try using the packages option like I mentioned before.

Routes, oh so dear routes
Your program works at first glance, but, hey! Your image/audio/video/whatever doesn’t! The folder is in data_files and the files are there. You don’t understand what is happening. So now you just want to hit the mat…

… Literally.
Maybe you have a little something like this?
path = os.path.dirname(__file__)
If you do, most static files and multimedia are stored in a .zip called library.zip and with this littler workaround it should work:
library_zip = path.split(“\\”)[-1]
if library_zip == ‘library.zip’: MAIN_PATH = os.path.dirname(os.path.dirname(__file__))
else: MAIN_PATH = os.path.dirname(__file__)
This will go to the parent of library.zip and then all your routes should work.
The annoying mail module
If you’re trying to compile a web framework like Flask or Django (Flask in my case), a most possible error will be this modules missing [‘email.Encoders’, ‘email.Generator’, ‘email.Iterators’, ‘email.MIMEBase’, ‘email.MIMEMultipart’, ‘email.MIMEText’, ‘email.Utils’, ‘email.base64MIME’]. And the solution is to add this lines to your setup.py:
modulefinder.AddPackagePath(“mail.mime”, “base”)
modulefinder.AddPackagePath(“mail.mime”, “multipart”)
modulefinder.AddPackagePath(“mail.mime”, “nonmultipart”)
modulefinder.AddPackagePath(“mail.mime”, “audio”)
modulefinder.AddPackagePath(“mail.mime”, “image”)
modulefinder.AddPackagePath(“mail.mime”, “message”)
modulefinder.AddPackagePath(“mail.mime”, “application”)
And then add email to your includes. Check and done!

Windows services skeleton
There are out there ways to create a windows service, but most of them are filled with unnecessary things like Windows events you don’t really need, so after a couple of google clicks plus some minor tweaks made a bunch of solutions into a simple one:
And now you just need to use this setup.py that works specifically with services:
With this, you can create services to do pretty much anything you want.

Compiling processes
This small snippet should go inside your program if you run processes of any kind:
from multiprocessing import freeze_support
# [..] Your code [..]
if __name__ == ‘__main’:
freeze_support()
p = Process(target=someFunc, args=(“test”, ))
p.start()
Python has the freeze_support feature inside the multiprocessing module which basically does all the hard work of telling the process that it’s going to be freeze.

Summary
I want to write this summary for 2 things that annoy me a lot about the view of the python community with py2exe.
First and foremost, py2exe is not useless. Nowadays in communities like StackOverflow and incite that you shouldn’t use py2exe just because It’s “too old” or “barely has any documentation”. This isn’t true, even though It’s entirely active It’s stable and contains far more examples and solutions than bbfreeze or cx_freeze.
Second, this guide is about general py2exe knowledge and not about x module working with py2exe. Which is what py2exe really needs, because one of the reasons there’s not many information is because most posts and information is about “how to make x thing in y module work with py2exe” when It’s most likely to be a generic error. If you need PyQt or PySide examples/guides with py2exe, a simple google search will point you out to a lot of handful examples, but most of them are general knowledge applied to a specific case in PyQt/PySide.

I hope this guide has served its purpose (or at least you got some cool boxing gifs). If you feel something’s missing, tweet me about it at @DoctorMalboro or leave a note somewhere in the post.