Create Executable File With PyInstaller, cx_Freeze, py2exe

Python is an interpreted language. This implies that users of our console or desktop applications (for example, those developed with tkinter, PyQt/PySide, wxPython, etc.) must have Python installed to run .py files. However, there are multiple tools that allow us to create executable files (.exe, .app, etc.) for Windows, Linux and Mac systems, so that our application can be executed without requiring the installation of Python. This makes it much easier to distribute our programs and improves user experience.

To get you started quickly, in this article we will briefly introduce the three main tools for creating executables and how to use them: PyInstaller, cx_Freeze and py2exe (the latter only for Windows). If you don't know which one to choose, just use PyInstaller.

PyInstaller

PyInstaller can generate executables for Windows, Linux and Mac with a simple command. First, let's make sure to install PyInstaller via pip:

pip install pyinstaller

Then, invoke the following command from the terminal in order to convert the main.py file to an executable:

pyinstaller main.py

If your application is made up of multiple .py files, just pass the main file (i.e., the file where the code to start the program lies.) The remaining files will be discovered by PyInstaller.

After running the command, the executable file will be found in the dist folder along with all its dependencies. The format and extension of the generated executable file will depend on the operating system from which the command was executed. On Windows we will get a .exe file, on Mac a .app file, and on Linux just an executable file without an extension. The build folder created during PyInstaller execution can be removed.

If you want PyInstaller to generate a single executable with no dependencies (files .dll, .so, etc.), pass the --onefile option:

pyinstaller --onefile main.py

Executables built with --onefile are easier to distribute, but take longer to initialize because dependencies must be extracted to a temporary folder before running the program.

For GUI applications, it will be better to tell PyInstaller not to show the console via the --noconsole option (options are combinable):

pyinstaller --noconsole main.py

By default the generated executables have the PyInstaller icon. To specify your own icon, use the --icon option followed by the path or name of the icon file:

pyinstaller --icon=file.ico main.py

The size of the final file can be reduced by compressing it with UPX via the --upx-dir option, by which you must specify the directory where compressor is installed. For example:

pyinstaller --onefile --upx-dir=C:\upx main.py

Finally, PyInstaller can encrypt Python source code files as long as a 16-digit key is provided via --key=16_digit_key:

pyinstaller --key=1234567891234567 main.py

This option requires the tinyaes package, installable via:

pip install tinyaes

cx_Freeze

cx_Freeze is very similar to PyInstaller, and can also generate executables for Windows, Linux, and Mac. You can install cx_Freeze via pip by running:

pip install cx_Freeze

Once installed, if the main file of our application is main.py, open a terminal where it is located and run:

cxfreeze -c main.py --target-dir dist

The -c option specifies the name of the file to convert and --target-dir the directory where cx_Freeze will store the executable file.

To set an image as an icon, use the --icon option:

cxfreeze -c main.py --icon=file.ico --target-dir dist

On Windows, the console can be hidden by adding the --base-name=Win32GUI option (options are combinable).

cxfreeze -c main.py --base-name=Win32GUI --target-dir dist

py2exe

py2exe, as the name suggests, is a distutils extension to generate executable files for Windows. Install py2exe via pip:

pip install py2exe

To generate an executable file, first create a file called setup.py like this:

from distutils.core import setup
import py2exe
setup(console=["main.py"])

Then invoke it with the py2exe option:

python setup.py py2exe

Like PyInstaller, the executable file will be found in the dist folder along with its dependencies, while build can be safely deleted.

For GUI applications, use the windows argument instead of console, to avoid showing the console:

from distutils.core import setup
import py2exe
setup(windows=["main.py"])

To configure an icon image, use the icon_resources option.

from distutils.core import setup
import py2exe
setup(
    console=[{
        "script": "main.py",
        "icon_resources": [(1, "file.ico")]
    }]
)

All dependencies can be included in a single file, similar to PyInstaller's --onefile option, by using:

from distutils.core import setup
import py2exe
setup(
    options={"py2exe": {"bundle_files": 1}},
    console=[{
        "script": "main.py"
    }]
)