> For the complete documentation index, see [llms.txt](https://kmanu225.gitbook.io/cs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kmanu225.gitbook.io/cs/software-engineering/compatibility/legacy-python2.md).

# Legacy Python 2

Python 2 reached end of life in January 2020, but old scripts and exploits written for it are still everywhere. Modern distributions no longer ship `pip` for Python 2, and current tools refuse to build Python 2 environments, so running such code takes a few pinned versions.

This page covers three approaches: an isolated **virtualenv** on the host, a throwaway **Docker** container, and **porting** the code to Python 3 when it is worth it.

## Check that Python 2 is available

```bash
python2 --version
```

If the interpreter is missing, install it from your package manager (on Debian/Ubuntu the package is `python2`, when the release still provides it). Otherwise use the Docker method below.

## Method 1: pip and a virtualenv

### Install pip for Python 2.7

The current `get-pip.py` no longer supports Python 2. Use the script frozen on the 2.7 branch:

```bash
cd /tmp
wget https://bootstrap.pypa.io/pip/2.7/get-pip.py
python2 get-pip.py
rm get-pip.py
```

### Create a Python 2 virtualenv

virtualenv can no longer create Python 2 environments starting with version 20.22.0, so pin an older release:

```bash
python3 -m pip install --user "virtualenv==20.15.1"
python3 -m virtualenv -p /usr/bin/python2 venv2
source venv2/bin/activate
```

Inside the environment, `python` and `pip` point to Python 2. Install the program's dependencies and run it:

```bash
pip install -r requirements.txt
python script.py
```

Many libraries dropped Python 2 support, so you may have to pin the last compatible versions (for example `requests<2.28`).

## Method 2: Docker

When the host has no Python 2 at all, the official image still exists and comes with `pip`:

```bash
docker run --rm -it -v "$PWD":/app -w /app python:2.7 python script.py
```

The current directory is mounted in `/app`, and the container is removed when the program exits. For dependencies, open a shell instead and install them first:

```bash
docker run --rm -it -v "$PWD":/app -w /app python:2.7 bash
```

## Method 3: Port the code to Python 3

For a program you want to keep, converting it is often simpler than maintaining a Python 2 setup. `2to3` handles most syntax changes (`print`, `except`, `dict.iteritems()`, ...):

```bash
2to3 -w script.py
```

`-w` writes the changes in place and keeps a `.bak` backup. `2to3` is deprecated and removed in Python 3.13, so run it with an older Python 3 if needed. Review the result by hand: string versus bytes handling (sockets, binary files, encodings) is the usual source of bugs it does not fix.
