Keep Jupyter notebook running after closing browser tab

Python 2.7Ipython NotebookJupyter

Python 2.7 Problem Overview


I use Jupyter Notebook to run a series of experiments that take some time. Certain cells take way too much time to execute so it's normal that I'd like to close the browser tab and come back later. But when I do the kernel interrupts running.

I guess there is a workaround for this but I can't find it

Python 2.7 Solutions


Solution 1 - Python 2.7

The simplest workaround to this seems to be the built-in cell magic %%capture:

%%capture output
# Time-consuming code here

Save, close tab, come back later. The output is now stored in the output variable:

output.show()

This will show all interim print results as well as the plain or rich output cell.

Solution 2 - Python 2.7

#TL;DR:

Code doesn't stop on tab closes, but the output can no longer find the current browser session and loses data on how it's supposed to be displayed, causing it to throw out all new output received until the code finishes that was running when the tab closed.

Long Version:

Unfortunately, this isn't implemented (Nov 24th). If there's a workaround, I can't find it either. (Still looking, will update with news.) There is a workaround that saves output then reprints it, but won't work if code is still running in that notebook. An alternative would be to have a second notebook that you can get the output in.

I also need this functionality, and for the same reason. The kernel doesn't shut down or interrupt on tab closes. And the code doesn't stop running when you close a tab. The warning given is exactly correct, "The kernel is busy, outputs may be lost."

Running

import time
a = 0
while a < 100:
    a+=1
    print(a)
    time.sleep(1)

in one box, then closing the tab, opening it up again, and then running

print(a)

from another box will cause it to hang until the 100 seconds have finished and the code completes, then it will print 100.

When a tab is closed, when you return, the python process will be in the same state you left it (when the last save completed). That was their intended behavior, and what they should have been more clear about in their documentation. The output from the run code actually gets sent to the browser upon reopening it, (lost the reference that explains this,) so hacks like the one in this comment will work as it can receive those and just throw them into some cell.

Output is kind of only saved in an accessible way through the endpoint connection. They've been working on this for a while (before Jupyter), although I cannot find the current bug in the Jupyter repository (this one references it, but is not it).

The only general workaround seems to be finding a computer you can always leave on, and leaving that on the page while it runs, then remote in or rely on autosave to be able to access it elsewhere. This is a bad way to do it, but unfortunately, the way I have to for now.

Related questions:

Solution 3 - Python 2.7

First, install

> runipy

pip install runipy

And now run your notebook in the background with the below command:

nohup runipy YourNotebook.ipynb OutputNotebook.ipynb >> notebook.log &

now the output file will be saved and also you can see the logs while running with:

tail -f notebook.log

Solution 4 - Python 2.7

I am struggling with this issue as well for some time now.

My workaround was to write all my logs to a file, so that when my browser closes (indeed when a lot of logs come through browser it hangs up too) I can see the kernel job process by opening the log file (the log file can be open using Jupyter too).

#!/usr/bin/python
import time
import datetime
import logging

logger = logging.getLogger()

def setup_file_logger(log_file):
    hdlr = logging.FileHandler(log_file)
    formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
    hdlr.setFormatter(formatter)
    logger.addHandler(hdlr) 
    logger.setLevel(logging.INFO)

def log(message):
    #outputs to Jupyter console
    print('{} {}'.format(datetime.datetime.now(), message))
    #outputs to file
    logger.info(message)

setup_file_logger('out.log')

for i in range(10000):
    log('Doing hard work here i=' + str(i))
    log('Taking a nap now...')
    time.sleep(1000)

Solution 5 - Python 2.7

If you've set all cells to run and want to periodically check what's being printed, the following code would be a better option than %%capture. You can always open up the log file while kernel is busy.

import sys
sys.stdout = open("my_log.txt", "a")

Solution 6 - Python 2.7

I've constructed this awhile ago using jupyter nbconvert, essentially running a notebook in the background without any UI:

nohup jupyter nbconvert --ExecutePreprocessor.timeout=-1 --CodeFoldingPreprocessor.remove_folded_code=False --ExecutePreprocessor.allow_errors=True --ExecutePreprocessor.kernel_name=python3 --execute --to notebook --inplace ~/mynotebook.ipynb > ~/stdout.log 2> ~/stderr.log &

  • timeout=-1 no time out
  • remove_folded_code=False if you have Codefolding extension enabled
  • allow_errors=True ignore errored cells and continue running the notebook to the end
  • kernel_name if you have multiple kernels, check with jupyter kernelspec list

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFloView Question on Stackoverflow
Solution 1 - Python 2.7SebView Answer on Stackoverflow
Solution 2 - Python 2.7PoikView Answer on Stackoverflow
Solution 3 - Python 2.7SaitejareddyView Answer on Stackoverflow
Solution 4 - Python 2.7flaviostutzView Answer on Stackoverflow
Solution 5 - Python 2.7Jing XueView Answer on Stackoverflow
Solution 6 - Python 2.7Sida ZhouView Answer on Stackoverflow