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.
1. %history
Magic Command
-
By running the following command in a notebook cell, you can display the code execution history:
%history
-
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.
# 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 fromprint
ordisplay
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')
2. Convert ipynb Files Directly to Python Scripts
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:
-
In Jupyter Notebook, go to File -> Download as -> Python (.py).
-
You can also use the command:
jupyter nbconvert --to python <ipynb file>
3. Creating a Custom Function to Retrieve Code Execution History
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.
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)
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()
A Brief Explanation
get_ipython().execution_count
retrieves the current cell number.- The function is adjusted to accept negative values for
start
andstop
. get_ipython().history_manager.get_range
is used to obtain the code execution history.
In the actual function I use, I’ve added more features such as:
- Commenting out magic commands.
- Displaying output content from
print
ordisplay
as comments.
However, for simplicity, I’ve omitted them here.