27

I would like to leave an IPython notebook running to do some computation + show some visuals.

Once the IPython notebook has finished, I want the last cell in the IPython notebook to programmatically save the IPython notebook. Then I want to copy the notebook (with all output) to another directory to keep a record of results.

The copying bit I can code up easily, but I am not sure how to get an IPython notebook to programatically save itself? Is this possible? Thanks in advance!

applecider
  • 2,311
  • 4
  • 19
  • 35
  • 1
    Saving is done from the notebook web interface, which the kernel doesn't really know about. But you could make a cell that [displays Javascript](http://ipython.readthedocs.org/en/stable/api/generated/IPython.display.html#IPython.display.Javascript) to call the frontend save function. – Thomas K Aug 26 '15 at 23:54
  • 2
    With IPython < 4, you could do something like: `from IPython.display import display,Javascript display(Javascript('IPython.notebook.save_checkpoint();'))` – Taar Aug 28 '15 at 03:44
  • @Taar, thanks! That was the answer I was looking for; would accept as answer if it were answer! – applecider Aug 28 '15 at 04:35

3 Answers3

20

I am taking @Taar's comment and making it an actual answer since it worked for the original person who asked the question and for myself.

from IPython.display import display, Javascript
display(Javascript('IPython.notebook.save_checkpoint();'))

This will create checkpoints - same thing as CTRL-s.

Note: in Jupyter, CTRL-s triggers an async process and the file save is actually completed only a few seconds later. If you want a blocking save operation in a notebook, use this little function (file_path is the path to the notebook file):

import time
from IPython.display import display, Javascript
import hashlib

def save_notebook(file_path):
    start_md5 = hashlib.md5(open(file_path,'rb').read()).hexdigest()
    display(Javascript('IPython.notebook.save_checkpoint();'))
    current_md5 = start_md5
    
    while start_md5 == current_md5:
        time.sleep(1)
        current_md5 = hashlib.md5(open(file_path,'rb').read()).hexdigest()
Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
Raphvanns
  • 1,766
  • 19
  • 21
  • If I am running this from the command line (on a remote server where I am not the user currently using the notebook) how do I specify which notebook I want saved? – zozo Jan 09 '20 at 03:33
  • @zozo, I have no ideas. Note: yours is an entirely different question since you are trying to save a notebook from outside, I suggest you open another new question. – Raphvanns Jan 10 '20 at 04:19
  • 3
    This won't work when using the JupyterLab interface, see [here](https://github.com/jupyterlab/jupyterlab/issues/7627). (Also I think the code should read `import time`, and not `from time import sleep`.) – Wayne Feb 14 '20 at 02:36
  • 5
    This unfortunately doesn't work with Jupyter Lab (3.2.5): I get `Javascript Error: IPython is not defined`. – Eric O. Lebigot Dec 31 '21 at 14:20
  • this great ! only issue ? : if you save it a second time without changes the hash never changes so it is blocked forever and just hangs. this fixes that: https://stackoverflow.com/a/73889852/1951317 – ox. Sep 29 '22 at 03:05
  • Where can I find similar commands to the `save_checkpoint` command? E.g. save and pin revision (Ctrl+M S) – Sterling Oct 08 '22 at 03:31
5

The ipython magic command %notebook will help you here. It is shown on this page (search for %notebook).

To save your current notebook history to the file "foo.ipynb" just enter:

%notebook -e foo.ipynb

At the point you want it to happen

or1426
  • 929
  • 4
  • 7
  • 4
    Be aware that this saves your *history* as a new notebook. If you've run the notebook from start to finish without re-running any cells and run this at the end, that will be what you expect. If you re-run or re-order any cells, it may not do what you want. – Thomas K Aug 26 '15 at 23:50
  • 1
    or1426, thanks but for some reason I am not getting the output in foo.ipynb, is there any way to do that? – applecider Aug 27 '15 at 04:53
  • Is there a way to dynamically add the path to save as well? Eg `%notebook path_variable_from_runtime\name.ipynb` – CodeCollector Jan 03 '18 at 15:50
  • 1
    if `some_python_var` is a python variable with the path you want, you can `%notebook $some_python_var` – fonini Feb 27 '19 at 20:58
0

In [1]:

import os
import time
import pathlib
from IPython.display import display, HTML, Javascript

html = '''
<script>
    IPython.notebook.kernel.execute(
        'filename = "' + IPython.notebook.notebook_name + '"'
    )
</script>
'''

def save_notebook():
    file_path = str(
        pathlib.Path(
            os.getcwd(),
            filename
        )
    )
    start_mtime = os.path.getmtime(file_path)
    display(
        Javascript(
            'IPython.notebook.save_checkpoint();'
        )
    )
    current_mtime = start_mtime
    while start_mtime == current_mtime:
        time.sleep(1)
        current_mtime = os.path.getmtime(file_path)

display(HTML(html))

In [2]:

save_notebook()

This works when you have not made any new changes to the notebook.

ox.
  • 3,579
  • 1
  • 21
  • 21