News icon

Kimi K3 is now available on Runpod

When (and why) to upgrade your Python version

Python versions carry a security clock and a performance upgrade you're leaving on the table — here's what changes when you move off an old interpreter, and when it's fine to wait.

When (and why) to upgrade your Python version

Every few weeks, a ticket comes in that isn't really about Runpod: a pip install failing halfway, a SyntaxError on a line that looks fine, a model repo that won't build. Trace it back and the interpreter baked into the image is usually too old for the library.

Nobody picks a Python version on purpose anymore. It's whatever the base image shipped with, or whatever conda defaulted to years ago. Fine, until it isn't. We're not exempt either. A number of Runpod's own official templates still default to pre-3.10 builds, and we're working through updating them.

What does Python end of life actually mean?

CPython retires versions on a fixed schedule. Once a version is end of life, it stops receiving security patches:

  • Python 3.6: EOL December 2021
  • Python 3.7: EOL June 2023
  • Python 3.8: EOL October 2024
  • Python 3.9: EOL October 2025
  • Python 3.10: in security-only mode now, full EOL October 2026

Run any of the first four in a container that touches the internet, downloads packages, or takes external input, and a newly discovered CVE in ssl, urllib, or anywhere in the standard library never gets patched. Nobody's backporting a fix to 3.8. That branch is closed.

One nuance: EOL applies to the whole branch, but fixes ship as point releases within it. A container "on 3.10" pinned to an old point release, say 3.10.4 from 2022, has been missing patches for years despite the branch being technically supported. Check the full version string, not just the major version.

Where does this actually break?

The security argument is real but abstract. The compatibility argument is the one that actually generates tickets.

NumPy, SciPy, and increasingly PyTorch follow SPEC 0, a shared policy that drops support for a Python version roughly three years after release. Past that age, assume you're outside the window for something in your stack. pip won't say so plainly, it just falls back to an old wheel, or finds none, and looks like a Runpod problem instead of a Python one.

Syntax is a quieter trap. The match statement and X | Y union syntax landed in 3.10. Paste either into a 3.9 container and you get a SyntaxError on a perfectly valid line, just not on your interpreter.

What do you get in return?

Everything above is a reason to stop something risky. There's also a reason to move: CPython's gotten meaningfully faster since 3.10, mostly for free.

It traces back to the Faster CPython project, started by Guido van Rossum and Mark Shannon at Microsoft in 2021. The biggest jump: 3.11, roughly 25% faster than 3.10 on average, 10-60% depending on workload, mostly from a specializing interpreter that swaps in cheaper bytecode for what your code actually does. Function calls got cheaper, startup got faster, and common modules are now frozen in instead of parsed from disk.

3.12 added faster inlined comprehensions and a leaner object model. 3.13 and 3.14 go further: an experimental JIT, and the first free-threaded build, Python without the GIL, letting threads run bytecode in parallel across cores. That build carried a real single-threaded cost early on; 3.14 made it officially supported and added incremental garbage collection, which helps tail latency (p99s) more than average throughput.

None of this touches your code, and upgrading alone can hand a CPU-heavy fleet real compute headroom. That upside isn't universal, though, it's limited to pure-Python, CPU-bound code. If your workload lives inside NumPy, PyTorch, or another compiled extension, or is waiting on a network call or GPU kernel, the interpreter was never your bottleneck. For ML, the gain shows up in the glue code: data loading, preprocessing, inference requests. Not training.

When is it fine to stay behind?

Pinning a version on purpose, for reproducibility, isn't the problem here. A frozen environment tied to a paper's results or a production model is a deliberate, reasonable tradeoff.

The problem is not knowing which situation you're in. "We pinned 3.8 because the training run depends on it and we've documented the tradeoff" is a fine answer. "Huh, I didn't know we were still on 3.8" is the one that turns into a support ticket.

How do you check, and fix, your Python version?

Inside a running Pod:

python --version

If that comes back 3.9 or earlier, you're outside the window on at least one thing you're likely to install. To move off it:

  • Custom Dockerfile: bump the base image tag (FROM python:3.11-slim instead of 3.8-slim) and rebuild.
  • Conda environment: conda create -n myenv python=3.11 and reinstall your dependencies into the new environment rather than upgrading in place.
  • Template-based Pods: check which Python version the template's base image ships with before you build a stack on top of it.

Either way, rebuild and test in a fresh Pod before pointing a production Serverless endpoint at it. A version bump often means requirements.txt needs updates too.

Common questions about Python end of life

Is Python 3.9 still supported?

No. Python 3.9 reached end of life in October 2025, so the Python core team no longer ships security patches for it.

What Python version should I use for machine learning?

Use one of the two most recent stable Python releases. Current PyTorch, NumPy, and SciPy releases are built and tested against that range, so staying inside it keeps you inside the compatibility window instead of guessing.

What actually happens if I keep using an end-of-life Python version?

The interpreter itself stops getting security patches, and current releases of major ML libraries eventually drop support for it. The second one is what people notice first, usually as a failed pip install or a wheel that silently falls back to an old version.

How do I upgrade Python in a Docker container?

Change the base image tag in your Dockerfile, for example FROM python:3.11-slim instead of python:3.8-slim, then rebuild the image. If you're using conda, create a new environment at the target version and reinstall into it rather than upgrading in place.

How do I check what Python version a Pod is running?

Run python --version in a terminal inside the Pod.

Will upgrading Python make my model training faster?

Not usually. The interpreter-level gains since 3.10 apply to CPU-bound pure-Python code. If most of your runtime is inside PyTorch or CUDA kernels, upgrading won't move training time much. It still helps the Python glue around the model, things like data loading, preprocessing, and inference-server request handling.

Does Python remove the GIL in newer versions?

Python 3.13 introduced an experimental free-threaded build that runs without the global interpreter lock (GIL), and 3.14 made that build officially supported rather than experimental. The standard GIL-enabled build is still the default; free-threading is opt-in.

Related articles

View All

Build what’s next.

Build, train, and scale AI workloads on Runpod with cloud GPUs, Serverless, and Clusters.

Star field background