Python
IPython Notebook
Python 2.x
Python 3.x
Dual Environment

Using both Python 2.x and Python 3.x in IPython Notebook

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If you still need both Python 2 and Python 3 in notebooks, the correct model is separate kernels, not one notebook process somehow switching interpreters mid-session. Modern Jupyter makes that possible, but Python 2 is end-of-life, so this setup should be treated as a legacy compatibility bridge rather than a long-term development strategy.

The Core Idea: One Kernel Per Interpreter

A notebook server can expose multiple kernels. Each kernel points at a specific interpreter and environment. That means:

  • one kernel can run Python 3
  • another kernel can run Python 2
  • each notebook chooses one kernel at a time

You are not mixing both runtimes inside one executed notebook cell stream. You are selecting between distinct environments.

Create Separate Environments

The safest setup is one isolated environment for Python 2 and one for Python 3. If you still have a Python 2 interpreter available, install a dedicated kernel package there.

Python 3 environment:

bash
1python3 -m venv venv-py3
2source venv-py3/bin/activate
3python -m pip install --upgrade pip ipykernel notebook
4python -m ipykernel install --user --name py3-env --display-name "Python 3"
5deactivate

Legacy Python 2 environment:

bash
1virtualenv -p python2 venv-py2
2source venv-py2/bin/activate
3pip install ipykernel
4python -m ipykernel install --user --name py2-env --display-name "Python 2 (Legacy)"
5deactivate

After that, the Jupyter interface can list both kernels.

Launch Jupyter and Select the Kernel

Start the notebook server from any environment that has Jupyter installed:

bash
jupyter notebook

When creating or opening a notebook, choose the kernel from the UI. Existing notebooks can also be reassigned to a different kernel, but remember that the code inside the notebook may not be compatible across versions.

Keep Dependencies Separate

The kernel name is only part of the story. The environment behind it also controls package versions. If one notebook needs pandas for Python 3 and another requires a legacy Python 2 library, install each dependency inside the matching environment instead of globally.

This is the main benefit of kernels over ad hoc interpreter switching. Each notebook runtime becomes reproducible.

Verify Which Python Is Running

Never assume you selected the correct kernel. Print the interpreter path directly in the notebook:

python
1import sys
2
3print(sys.version)
4print(sys.executable)

This is especially useful on shared systems where multiple kernels have similar names.

Compatibility Realities in 2026

Python 2 has been end-of-life for years. That means:

  • many libraries no longer publish Python 2 compatible versions
  • security support is gone
  • packaging tools may break in newer environments

If you only need to inspect or migrate old notebooks, keep the Python 2 kernel as isolated and minimal as possible. Do not build new application logic around it.

A Better Medium-Term Strategy

If the legacy notebook still matters, a practical migration path is:

  1. keep the original notebook runnable with the legacy kernel
  2. create a Python 3 copy
  3. port imports, print statements, and text-handling differences incrementally
  4. remove the Python 2 kernel once the migrated notebook passes validation

That lets you preserve a working reference while moving toward a maintainable environment.

Common Pitfalls

  • Expecting one notebook kernel to switch between Python 2 and Python 3 during execution.
  • Installing Jupyter globally and losing track of which environment owns which kernel.
  • Reusing the same display name for multiple kernels and selecting the wrong one.
  • Assuming package availability will be similar across Python 2 and Python 3.
  • Keeping Python 2 around longer than necessary after the migration work is done.

Summary

  • Use separate Jupyter kernels, one per interpreter version.
  • Isolate Python 2 and Python 3 in different environments.
  • Verify the active interpreter inside the notebook with sys.version and sys.executable.
  • Treat Python 2 support as a temporary compatibility layer, not a new baseline.
  • Plan a migration path so the legacy kernel can eventually be removed.

Course illustration
Course illustration

All Rights Reserved.