6 ways to package Python apps for re-use

Do you have a Python application you want to give to the world, or at least your teammates? Here are six ways to package Python applications for distribution.

it as a product box package hand with product technology nodes primary

Python's explosive growth over the last decade has shown the world it's a powerful and flexible way to accomplish very nearly anything you want to do in computing. It's also clear that Python still has a few painful shortcomings that can't be ignored.

One of Python's biggest shortcomings is that it's hard, often unreasonably so, to take a Python program you've written and just give it to someone else. Languages like C and C++, and now Go and Rust, have build tools that generate a standalone binary artifact. Python, an interpreted language, requires its runtime in order to do anything. But bundling the runtime with your code is at best a clumsy process.

Generally, you would "distribute" a Python application by giving someone the source code and telling them how to set up the Python runtime (if they don't have it already) and any dependencies for the application. There are tools you can use to generate a standalone redistributable (essentially, an artifact that can be unpacked on a system without Python and run as-is) but currently they're all third-party, ad-hoc solutions.

As of 2022, there's still no formal way to turn a Python program into a standalone item. The good news is that, depending on the task at hand and the people involved, you might be able to get away with using a more conventional method to distribute your Python applications.

This article looks at various ways to provide Python applications for others to consume. In some cases, the target user will have to install the Python runtime; in others, you can distribute the application as a standalone.

Create a pip installable package

Using pip is the most conventional and best-supported way to package a Python application for re-use. Just take your application directory and outfit it with a setup.py file, which turns it into a pip-installable package. Anyone can then launch the resulting program by adding a command to the scripts directory of their Python installation, using the entry points specification in setup.py.

You don't have to provide the package through PyPI, either. You could host it in a Git repository, and then pip install from it using the git+https://url.to.repository format (for web-hosted repos).

Requires runtime

Yes.

Allows bundling of data

Yes, by way of the MANIFEST.in file, but it's generally best to consider this data read-only.

Pros

Uses Python's own setup mechanisms. Easy to install using pip.

Cons

Requires making a setup.py file and learning how to use the setuptools library. Also, if the application requires read-write access to data, it will need to place that data somewhere other than the site-packages directory where it's been installed. Any behaviors outside of what's officially supported by a pip install-able package can't be handled by the install process itself.



Use PyInstaller, py2exe, Nuitka, or another bundling solution

The most convenient way to deliver a Python application to a user is to provide them with an executable—either a single file or a directory with an easily identified executable somewhere in it. To do this, you would employ a third-party program to package the application and all its dependencies, and bundle it with a copy of the runtime.

PyInstaller is the most well-known program of this kind, and one of the best supported. It's extensible enough to allow you to bundle the data and auxiliary files, and provides a good deal of control over the resulting bundle—you can even set the icon used in the executable. Another solution, Py2exe, works similarly, although it doesn't provide some of the bundling options, such as the ability to generate a single self-unpacking executable.

A third project, Nuitka, also creates a redistributable package, but it's a more ambitious project overall. It converts a Python program and its associated libraries into a C++ executable with performance optimizations. (Currently, those optimizations are very much a work in progress.)

Yet another solution is the BeeWare suite, which developers can use to write and deploy Python applications in a cross-platform manner.

Requires runtime

No.

Allows bundling of data

Yes, by way of a manifest file, which needs manual configuration.

Pros

Generates single artifacts—a bundle with an executable that can be unpacked and run conveniently. When it works, it's arguably the most convenient solution as far as the user is concerned.

Cons

Does not always detect every third-party dependency needed; sometimes needs additional hints as to what libraries to add to the bundle. The resulting .exe in the bundle is also sometimes flagged as a false positive by antivirus solutions (you can work around this issue by custom-compiling the .exe).

PyInstaller also doesn't cross-compile. Windows .exes can only be created on Windows, and bundles for macOS and Linux can only be created on those systems. Py2exe only supports Windows. Nuitka is also highly experimental because it compiles Python to C++. Some applications might not work with it at all.

With BeeWare, you have to write the application using the BeeWare libraries to make the program work in a cross-platform way. At the very least, you would need to use the Briefcase library to package a program for delivery.



Use Zipapps or Shiv

If your program only consists of a few files with no external dependencies, you could use an application bundling system that's included with Python itself: the Zipapp standard. A directory of Python files (essentially, a module) can be packaged into a .pyz file—a .zip-format archive—and given to someone else who has the Python runtime. One click on the .pyz file, or a simple python file.pyz command, launches the application.

The big drawback of Zipapps is that it can't elegantly bundle third-party packages. To that end, the Shiv library, created by developers at LinkedIn, adds features to turn .pyz files into self-extracting archives that unpack dependencies, including binaries, into a subdirectory.

Requires runtime

Yes.

Allows bundling of data

Not readily; you need to bundle the data as if it were part of a package or include it with the zipapp in an archive. shiv makes this incrementally easier.

Pros

Uses native Python mechanisms for bundling apps.

Cons

It's hard to pack up third-party modules. shiv makes it possible but at the cost of requiring you to write a setup.py configuration for your program.



Host as a web service

If your application only needs to be accessible by way of a web interface—or if that's the only kind of access you want to grant—you can simply host the application as a web service. An application that only needs to be available locally could be hosted on your own servers, and perhaps made available through a VPN connection. A public-facing application could be hosted using an application cloud-hosting service.

If your Python application is hosted using a Jupyter notebook, it's possible to set up a public (or at least internal) server for it using JupyterHub.

Requires runtime

Yes, you must host the application with a runtime for others to access.

Allows bundling of data

Yes, although the data will have to be included manually on the server side.

Pros

Can be accessed through a web interface.

Cons

The application is only accessible through a web interface. A console-based application, for instance, or something with a GUI, will need to be retooled to work as a web application. Some applications may not work well when packaged this way.

Any public-facing application will need to have appropriate security measures set up. This includes hosted Jupyter notebooks, which have their own peculiar security issues.



Use containers

Containers (of the Docker variety) have fast become a deployment standard for server-side applications, with every major operating system building in support for them. It's no more difficult to "Dockerize" a Python application, like a web application, than it is to build a container for most any other application that uses some sort of runtime.

Requires runtime

No, the runtime is bundled with the container.

Allows bundling of data

Yes, as part of the standard system for including data in a container.

Pros

It's a widely used standard.

Cons

Requires the presence of a Docker-like platform on the target; not well suited to desktop apps.



Create an embeddable package on Windows

Windows users have yet another option, although it involves the most heavy lifting of all. To start, you can download an embeddable package version of Python for Windows as a .zip file. This is a minimal, self-contained installation of Python that lives in a single directory, including the standard library. It's possible to place a Python application in this directory, along with its dependencies and data files. You can install the dependencies into the embeddable's directory with pip—but note that you need to use the pip from the Python installation you used to create the application, not from the embeddable package itself. (Watch a video demonstration to learn more about this concept.)

Requires runtime

No, it's bundled with the app.

Allows bundling of data

Yes, although the process is entirely manual.

Pros

Everything is bundled in one directory.

Cons

Manually creating such a bundle is difficult, and often requires much trial and error to get right.

Copyright © 2022 IDG Communications, Inc.