stdout redirect from Jupyter notebook is landing i

2019-01-28 18:33发布

问题:

So I was trying to redirect stdout for a some of the cells in my Jupyter Notebook to a file with this and then cancel it with this for the rest of the cells. The output from the first set of cells landed in the file like it was meant to. The second set of cells after the cancel command sys.stdout = sys.__stdout__ was giving no output, appearing to do nothing, but I later realised it was landing in the terminal where the notebook was launched.

It works perfectly in the Python interpreter with exactly the same Python:

(miniconda3-latest) cardamom@pegasus:~/Documents/project1 $ python
Python 3.6.0 |Continuum Analytics, Inc.| (default, Dec 23 2016, 12:22:00) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.stdout = open('stdout.txt', 'w')
>>> print("a")
>>> print("a")
>>> print("a")
>>> sys.stdout = sys.__stdout__
>>> print ("b")
b
>>> print ("b")
b
>>> print ("b")
b
>>> # lots of a's are in the file and no b's

A similar approach in the Jupyter notebook is giving this in the terminal:

[W 22:05:34.192 NotebookApp] 404 GET /nbextensions/widgets/notebook/js/extension.js (127.0.0.1) 1.71ms referer=http://localhost:8889/notebooks/test_stdout.ipynb
b
b
b

How can this code be adapted so that after resetting it, I get the b's appearing under the cells where the output usually goes instead of in the terminal?

回答1:

I'm not able to test that but the only explanation I see is that sys.stdout is not sys.__stdout__ but a rerouted/modified file object in order to be able to put data in cells (your comment indicates that it's a ipykernel.iostream.OutStream instance).

So instead of resetting to sys.__stdout__, you should store the reference of sys.stdout:

import sys
old_stdout = sys.stdout
sys.stdout = open('stdout.txt', 'w')
...
sys.stdout = old_stdout

Note that this method also works with a standard terminal.