When you choose Python for software development, you get a large language ecosystem with a wealth of packages covering all manner of programming needs. But in addition to libraries for everything from GUI development to machine learning, you can also choose from a number of Python runtimes—and some of these runtimes may be better suited to the use case you are working on than others.
Here’s a brief tour of Python distributions, from the standard implementation (CPython) to versions optimized for speed (PyPy), special use cases (Anaconda, ActivePython), different language runtimes (Jython, IronPython), and experimental use cases (MicroPython, RustPython).
CPython is the Python reference implementation, the standard version that all other Python incarnations look to. CPython is written in C, as implied by the name, and is produced by the same core group of people responsible for making top-level decisions about the Python language.
Use cases for CPython
Because CPython is Python’s reference implementation, it has historically been the most conservative runtime in terms of optimizations. Python’s maintainers want CPython to be the most broadly compatible and standardized implementation of Python available. However, over the last few revisions, the development team has introduced optimizations designed to make Python generally faster, with more ambitious work planned—but never at the cost of backward compatibility.
CPython is your best choice when compatibility and conformity to Python standards matter more than raw performance and other concerns. CPython is also useful for the expert who wants to work with Python in its most fundamental incarnation, and who is willing to forgo certain conveniences.
For example, with CPython, you have to do a little more lifting to set up virtual environments. Other distros (Anaconda, in particular) provide more automation around workspace setup.
CPython has few of the performance optimizations found in other editions of Python. It does not have a native JIT (just-in-time) compiler, accelerated math libraries, or third-party additions for performance. Those are all features you can add on your own, but they’re not bundled. Again, this is done purposefully to ensure maximum compatibility and allow CPython to serve as a reference implementation. But it means any performance optimizations are up to the developer.
Further, CPython provides only a baseline set of tools for working with Python. The
pip package manager, for instance, obtains and installs packages from Python’s native PyPI package repository. Pip will even install precompiled binaries (via the wheel distribution format) if you provide them, but it won’t install any dependencies that packages might have outside of PyPI.
Anaconda, produced by Anaconda Inc. (formerly Continuum Analytics), is designed for Python developers who need a distribution backed by a commercial provider and with support plans for enterprises. The chief use cases for Anaconda Python are math, statistics, engineering, data analysis, machine learning, and related applications.
Use cases for Anaconda Python
Anaconda bundles many of the most common libraries used in commercial and scientific Python work—SciPy, NumPy, Numba, and so on—and makes many more of them accessible via a custom package mamagement system.
Anaconda stands out from other distributions in how it integrates all these pieces. When installed, Anaconda provides a desktop app—the Anaconda Navigator—that makes every aspect of the Anaconda environment available through a convenient GUI. Finding components, keeping them up to date, and working with them is a good deal easier out of the box with Anaconda than with CPython.
Another boon is the way Anaconda handles components from outside the Python ecosystem if they’re required for a specific package. The
conda package manager, created specifically for Anaconda, handles installing both Python packages and third-party, external software requirements.
Anaconda Python’s limitations
Because Anaconda includes so many useful libraries, and can install even more with only a few keystrokes, the size of an Anaconda installation can be much larger than CPython. A basic CPython installation runs about 100MB; Anaconda installations can grow to gigabytes in size. This can be an issue in situations where you have resource constraints.
One way to reduce Anaconda’s footprint is to install Miniconda, a stripped-down version of Anaconda that includes only the absolute minimum of pieces needed to get up and running. You can then add packages to Miniconda as you see fit, with an eye toward how much space each piece consumes.
Like Anaconda, ActiveState Python is created and maintained by a for-profit company—in this case, ActiveState, which markets a number of language runtimes along with the multi-language Komodo IDE.
Use cases for ActiveState Python
ActiveState Python is aimed at enterprise users and data scientists—people who want to use Python, but don’t want to spend much effort assembling and managing a Python installation. ActiveState uses Python’s regular
pip package manager, but also supplies a few hundred common libraries as verified pack-ins, along with some common libraries with third-party dependencies such as the Intel Math Kernel Library.
ActiveState Python’s limitations
There is one potential drawback to ActiveState’s approach to handling packages with external dependencies. If you want to upgrade to a newer version of a project with complex dependencies (for example, TensorFlow), you will need to upgrade your ActiveState Python installation as well. In environments where development tends to be tied to a specific version of a project, this is less of an issue. But in environments where development tracks with cutting-edge versions, it could present a problem.
Additionally, ActiveState Python versions tend to lag behind the latest version of CPython. For instance, as of this writing, the latest supported version of Python is 3.12, but ActiveState only provides 3.10.
A drop-in replacement for the CPython interpreter, PyPy uses JIT compilation to speed up the execution of Python programs. Depending on the task, the performance gains can be dramatic.
Use cases for PyPy
A common complaint about Python generally, and CPython in particular, is speed. By default Python runs many times slower than C, sometimes hundreds of times slower. PyPy JIT-compiles Python code to machine language, providing a 4.8 times speedup over CPython on average. Some tasks run as much as 50 times faster.
The best part is that there is little to no effort required on the part of the developer to unlock these gains. Swap out CPython for PyPy, and for the most part you’re done. Also, all major platforms are supported in 64-bit editions—Windows, CentOS 7-compatible Linux (both ARM64 and Intel), and macOS (also both ARM64 and Intel).
PyPy has always performed best with “pure” Python applications. Python packages that interface with C libraries, such as NumPy, have not fared as well due to the way PyPy emulated CPython’s native binary interfaces. Over time, though, PyPy’s developers have whittled away at this issue, and made PyPy far more compatible with the majority of Python packages that depend on C extensions. In short, support for C extensions is still limited, but far less so than it used to be.
Another possible downside with PyPy is the size of the runtime. The core CPython runtime on Windows, excluding the standard library, is around 6MB, while the PyPy runtime is around 43MB.
The JVM (Java virtual machine) serves as the runtime for a great many languages besides Java. The list includes Kotlin, Groovy, Scala, Clojure, and, yes, Python, by way of the Jython project.
Use cases for Jython
Jython compiles Python 2.x code to JVM bytecode and runs the resulting program on the JVM. In some cases a Jython-compiled program will run faster than its CPython counterpart, but not always.
The biggest advantage Jython provides is direct interoperability with the rest of the Java ecosystem. Running Python on the JVM allows Python developers to tap into an enormous ecosystem of libraries and frameworks that they otherwise wouldn’t be able to use. By the same token, Jython allows Java developers to use Python libraries.
The biggest drawback to Jython is that it supports only the 2.x branch of Python. Support for Python 3.x is under development, but so far nothing has been released.
Note, too, that while Jython brings Python to the JVM, it does not bring Python to Android. Because there is currently no port of Jython to Android proper, Jython can’t be used to develop Android applications.
Just as Jython is an implementation of Python on the JVM, IronPython is an implementation of Python on the .Net runtime, or CLR (Common Language Runtime). IronPython uses the DLR (Dynamic Language Runtime) of the CLR to allow Python programs to run with the same degree of dynamism that they do in CPython.
Use cases for IronPython
Like Jython, IronPython is a bridge. The big use case is interoperability between Python and the .Net universe. Existing .Net assemblies can be loaded in IronPython programs using Python’s native import and object-manipulation syntax. It is also possible to compile IronPython code into an assembly and run it as-is or invoke it from other languages. However, note that the MSIL (Microsoft Intermediate Language) in the assembly cannot be directly accessed from other .Net languages, as it is not compliant with the Common Language Specification.
IronPython supports Python 2.7 and also Python 3, but the latest version of Python 3 supported is Python 3.4. This greatly limits how much of the existing Python ecosystem it can work with, since the 3.4 version has been unsupported for some time now.
As the name implies, WinPython is a Python distribution created specifically for users of Microsoft Windows. CPython’s earlier editions for Windows were not well designed, and it was difficult for Windows users to take full advantage of the Python ecosystem. CPython’s Windows edition has improved over time, but WinPython still offers many things not found in CPython.
Use cases for WinPython
WinPython’s main attraction is that it’s a self-contained edition of Python. It doesn’t have to be installed on the machine where it runs; it just needs to be unpacked into a directory. This makes WinPython useful in cases where software can’t be installed on a given system; in scenarios where a preconfigured Python runtime needs to be distributed along with the applications to run on it; or where multiple editions of Python need to run side-by-side without interfering with each other.
CPython itself does comes in an unpack-and-run format—it’s called the “embeddable redistribution”—but it’s deployed with an extremely minimal complement of packages. By contrast, WinPython bundles a slew of data science oriented packages—NumPy, Pandas, SciPy, Matplotlib, etc.—so they can be used right away, without additional installation steps. Also included is a C/C++ compiler, since many Windows machines don’t have one included, and many Python extensions require or can make use of it.
One limitation of WinPython is that it might include too much by default for some use cases. To remedy that, WinPython’s creators provide a “zero” version of each WinPython edition, containing only the most minimal possible install of the product. More packages can be added later, either with Python’s own
pip tool or WinPython’s WPPM utility.
Use cases for Python Portable
Like WinPython, Python Portable includes a slew of packages for scientific computing—Matplotlib, Numba, SymPy, SciPy, Cython, and others. Also like WinPython, Python Portable runs without needing to be formally installed on the Windows host; it can live in any directory or on a removable drive. Also included is the Spyder IDE and Python’s
pip package manager, so you can add, change, or remove packages as needed.
Python Portable’s limitations
Unlike WinPython, Python Portable does not include a C/C++ compiler. You’ll need to provide a C compiler to use code written with Cython (and thus compiled to C). Also, the most recent version of Python offered as of this writing is 3.9.
Experimental Python distributions
These distributions make significant changes to Python—either because they’re using Python as a starting point for something entirely new, or because they’re making strategic changes to standard Python. By and large, these Pythons are not recommended for production use yet.
If you’re living with a Python 2.x codebase for the foreseeable future, you might want to check out our article about the experimental Python distributions keeping Python 2.x alive.
MicroPython provides a minimal subset of the Python language that can run on extremely low-end hardware such as microcontrollers. MicroPython implements Python 3.4 with some differences. It’s easy to write MicroPython code if you know Python, but existing code may not run as-is.
The default Python runtime, written in C, is by many accounts high-quality code that minimizes the number of booby traps exposed by the C language. The RustPython project implements a Python runtime in the Rust language, taking advantage of Rust’s memory safety and speed. It currently supports only a subset of Python’s syntax, but it’s making steady progress. You can even try out a live demo in the browser.
Copyright © 2023 IDG Communications, Inc.