9

I have a notebook that runs overnight, and prints out a bunch of stuff, including images and such. I want to cause this output to be saved programatically (perhaps at certain intervals). I also want to save the code that was run. In a Jupyter notebook, you could do:

from IPython.display import display, Javascript
display(Javascript('IPython.notebook.save_checkpoint();'))
# causes the current .ipynb file to save itself (same as hitting CTRL+s)

(from Save an IPython notebook programmatically from within itself?)

Although, I found that this javascript injection did not work in Jupyter lab(Jupyter not found). My question is how to do the equivalent of the above code in Jupyter lab. Upon inspecting the HTML of the jupyter lab, I could not find the Jupyter object.

krassowski
  • 13,598
  • 4
  • 60
  • 92
charles strauss
  • 185
  • 1
  • 6

3 Answers3

8

You can use ipylab to access JupyterLab API from Python. To save the notebook just invoke the docmanager:save command:

from ipylab import JupyterFrontEnd

app = JupyterFrontEnd()
app.commands.execute('docmanager:save')

You can get the full list of commands with app.commands.list_commands().

krassowski
  • 13,598
  • 4
  • 60
  • 92
2

JupyterLab has a bulit-in auto-save function. You can configure the time interval using the Advanced Settings Editor, the Document Manager section (see screenshot below).

autosave config

However, if you really want a JavaScript solution you could just invoke the keyboard shortcut Ctrl + s with:

from IPython.display import display, Javascript

display(Javascript(
    "document.body.dispatchEvent("
    "new KeyboardEvent('keydown', {key:'s', keyCode: 83, ctrlKey: true}"
    "))"
))

this will only work as long as you do not change focus to a different notebook. However, you can always use an invisible HTML node such as input to reclaim the focus first:

from IPython.display import display, HTML

script = """
this.nextElementSibling.focus();
this.dispatchEvent(new KeyboardEvent('keydown', {key:'s', keyCode: 83, ctrlKey: true}));
"""
display(HTML((
    '<img src onerror="{}" style="display:none">'
    '<input style="width:0;height:0;border:0">'
).format(script)))

And you can always wrap the script in window.setTimout or window.setInterval - but it should not be needed thanks to the built in auto-save function of JupyterLab.

krassowski
  • 13,598
  • 4
  • 60
  • 92
  • Note: this will need adjustment on Mac OS which uses different default keys for save. – krassowski Apr 01 '21 at 20:47
  • 1
    Thanks, this is a great solution. I wonder if there is a way to make jupyter save even when my screen is black, and my browser might not be active, so a server-side method that does not require an active client? – charles strauss Apr 05 '21 at 23:12
2

I just wanted to share a really small tweak of the other solution by krassowski that works for JupyterLab on MacOS:

from IPython.display import display, HTML

script = """
this.nextElementSibling.focus();
this.dispatchEvent(new KeyboardEvent('keydown', {key:'s', keyCode: 83, metaKey: true}));
"""
display(HTML((
    '<img src onerror="{}" style="display:none">'
    '<input style="width:0;height:0;border:0">'
).format(script)))
dnola
  • 61
  • 5