💾 Archived View for ajdiaz.me › doc › 2015 › 09101-python-binaries.txt captured on 2022-06-04 at 00:44:35.
-=-=-=-=-=-=-
A procedure to package python applications as static-linked binaries. http://ajdiaz.me/doc/2015/09101-python-binaries.txt Version: 2015-09-10 One of the major problems with python applications is that they required to install the entire python virtual machine and core library to run. This is not a problem in most cases, but sometimes could be annoying, specially in machines with few resources. This paper explorer the idea to create a binary, statically linked, which can run a python application. The main idea behind this approach is based in two well-known behaviour of python and ZIP format. Almost since python2, the virtual machine has the ability to run a ZIP file as any other module, if `__main__.py` file exists inside. On the other hand, ZIP files allow some garbage before the ZIP header, and in that case, the parser must ignore that garbage. So, using this two behaviours, we can create a zip file with our application (let's call app.zip), and then create a macro binary in the form: cat /usr/bin/python app.zip > myexe And run ./myexe myexe. That's fine, but is far away that we want. But, it's easy to recompile python statically (some minor patch needs to be apply), and modify `main()` function to execute PyInit over the argv[0], that is, interpreting the self binary as application. Doing this modifications, whe can create new executable: cat ./static-python app.zip > myexe In that case when we run `myexe`, probably we got a number of errors, because the core library is not included, but is easy to solve, adding the core library to the zipfile. This approach has some advantages in comparisson with others. The first one is that we do not need to change the normal behaviour of python virtual machine (except to compile it statically), the second one is that any other data file required by the app could be added to the app.zip package. The big problem is that some modules wants to open files relatively to the module python file (i.e. open from __file__ path), which cannot work since the path is now the binary file. In this case we need to perform some kind of monkey patching to subsitute the open call to a pkgresource call and read the file using the proper function.