How to Save Jupyter Notebook's Code Execution History as a Python Script

In this article, I’ll introduce how to save the code execution history from Jupyter Notebook (JupyterLab) as a Python script.

First, I’ll go over the commonly used %history magic command and then share a custom function I’ve written.

Note
This method also works with Google Colaboratory.
  • By running the following command in a notebook cell, you can display the code execution history:

    %history
    
  • Official Documentation

  • Key Options:

    Option Description
    -n Shows line numbers.
    -o Displays output as well. (Note: Not all outputs are shown.)
    -p Prefixes commands with >>> (makes it easier to read when using -o).
    -t Translates magic commands and aliases into Python code.
    -f <FILENAME> Saves results to a file.
Example
# In [1] --------------------
a = 2
b = 3

# In [2] --------------------
a + b

# In [3] --------------------
display(a * b)

# In [4] --------------------
print(a - b)

# In [5] --------------------
%history
  • Execution Result:

    a = 2
    b = 3
    a + b
    display(a * b)
    print(a - b)
    %history
    
  • Displaying line numbers with -n.

       1:
    a = 2
    b = 3
       2: a + b
       3: display(a * b)
       4: print(a - b)
       5: %history -n
    
  • Displaying execution results using -o.
    (Note: Outputs from print or display are not shown.)

    a = 2
    b = 3
    a + b
    5
    display(a * b)
    print(a - b)
    %history -o
    
  • Converting magic commands to Python code with -t.

    a = 2
    b = 3
    a + b
    display(a * b)
    print(a - b)
    get_ipython().run_line_magic('history', '-t')
    

Although it slightly deviates from the topic of execution history, you can use the methods below to directly convert a notebook to a Python script:

  1. In Jupyter Notebook, go to File -> Download as -> Python (.py).

  2. You can also use the command:

    jupyter nbconvert --to python <ipynb file>
    

Since the two methods above didn’t give me the desired output, I decided to create a custom function based on the %history command’s code.

A Note on Motivation

During my machine learning experiments, I found myself wanting to save the code I executed in the notebook along with the experiment results.

I was using a local ipynb file and executing it on a remote server through VSCode. So, converting the ipynb file directly into a Python script on the remote side was not an option.

Moreover, the %history command couldn’t fulfill all my needs, which led me to design a custom function.

I wanted:

  • Separate outputs for each cell.
  • To execute the output directly in Python without any modifications.
from IPython import get_ipython


def get_history_simple(start=0, stop=None):
    """Retrieve Jupyter Notebook's code execution history.

    Args:
        start (int, optional): Start cell number. Defaults to 0.
        stop (int or None, optional): End cell number. Defaults to None.

    Returns:
        str: Code execution history
    """
    cell_num = get_ipython().execution_count
    if start < 0:
        start = cell_num + start
    if stop is not None and stop < 0:
        stop = cell_num + stop

    if stop is not None:
        stop += 1

    hist = get_ipython().history_manager.get_range(
        raw=True, output=False, start=start, stop=stop
    )
    codes = []
    for _, lineno, inline in hist:
        if inline.strip() == "":
            continue
        codes.append(f'# In [{lineno}] ' + '-' * 20)
        codes.append(f'{inline}\n')
    return "\n".join(codes)
Example

When executed, you’ll get an output like the following:

# In [1] --------------------
from jupyter_utils import get_history_simple

# In [2] --------------------
a = 2
b = 3

# In [3] --------------------
a + b

# In [4] --------------------
display(a * b)

# In [5] --------------------
print(a - b)

# In [6] --------------------
get_history_simple()
  • get_ipython().execution_count retrieves the current cell number.
  • The function is adjusted to accept negative values for start and stop.
  • get_ipython().history_manager.get_range is used to obtain the code execution history.
Note

In the actual function I use, I’ve added more features such as:

  • Commenting out magic commands.
  • Displaying output content from print or display as comments.

However, for simplicity, I’ve omitted them here.

Related Content