Wrapping Python applications into self-extracting executable files using Pyinstaller

In this short article, we will explore a simple way that allows you to distribute applications created in Python as thick, self-extracting archives that look like simple executable files and contain all the environment and dependencies necessary to run an application.

For the first time, such a problem happened in our project when distributing agents for a system in which nodes had restrictions on installing third-party software. The standard approach with installing dependencies and additional libraries through the package management system, PIP or in the form of Docker containers was not possible, so we started looking for a tool that would allow us to pack everything we need into a single executable file.

Fans of the Go language often mention distribution as a single file as a key advantage. Python allows you to implement a similar, though not equivalent, delivery.

During the search, we found the Pyinstaller tool. This tool is specifically designed to solve the problem of packaging Python software into executable files that have minimal external system dependencies.

Pyinstaller is designed to support Python libraries by default, however, developers keep the list for tested components, among which you can find a couple of which are not supported. In fact, this means that you have to make sure yourself that your software can be successfully distributed using Pyinstaller. For example, we successfully used the following libraries as part of our software:

mysql-connector
tornado
pyhocon

None of them at the time of publication is declared as verified, however, we have not encountered a single problem. However, the authors maintain a special page When Things Go Wrong , where you can learn what to do in case of problems

Supported Python Versions

At the time of publication, Pyinstaller supports Python versions 2.7, 3.4-3.7.

Simple Application Build With Pyinstaller

Let’s create requirements.txt, all libraries except for pyinstaller are for example and are not required for Pyinstaller operation:

pyinstaller
mysql-connector
tornado
pyhocon

Install the dependencies with PIP:

pip install --user -r requirements.txt

Make the application:

pyinstaller --workpath /tmp/build --specpath /tmp -F application.py

The -F flag specifies that everything will be packaged into a single executable file. The --workpath and --specpath paths determine where the build information will be placed, which will be used for the current and subsequent builds.

Crossbuilds

Pyinstaller does not support cross-build from one platform for all others. Authors advise you to deploy a separate platform for each build environment. In some cases, it is a disadvantage, since it requires the support of several build environments and can create problems for simple assembly using standard CI/CD tools, which focus on calling a single handler.

If you liked the article, share it with friends.