1

I am writing a custom client (a web-based graph representation of an IPython Notebook) for an IPython application and the easiest way to manage IPython programmatically seems to be using the IPython.core.InteractiveShell instance.

Consider this example: when a Jupyter Notebook cell that uses rich output is executed with inline magic, Notebook shows the appropriate rich representation (a plotted image) of plt.show() inline:

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
t = np.arange(0.0, 2.0, 0.01)
s = np.sin(2*np.pi*t)
plt.plot(t, s)
plt.xlabel('time (s)')
plt.ylabel('voltage (mV)')
plt.title('About as simple as it gets, folks')
plt.grid(True)
plt.show()

I want to be able to retrieve the image when using IPython programmatically via its API, namely InteractiveShell, like this:

from IPython.core.interactiveshell import InteractiveShell
shell = InteractiveShell()
result = shell.run_cell("...above code of the cell here...")
# result either gives an error when using %matplotlib inline or retrieves
# no useful info if no line magic is present

Problem is that InteractiveShell instance will not accept the %matplotlib inline magic, giving a NotImplementedError in its enable_gui method which is, wll, not implemented. I found very few information about this apart from a single issue on IPython's Github.

I know I can do this manually by using plt.save() but that doesn't seem right to me as I don't want to write manual interpretations each time I need another rich representation of the result. I feel like I'm missing a lot here in the way IPython works, so I'm asking for help in retrieving the results. What exactly does Jupyter Notebook do to retrieve the rich representation and perhaps can it be done painlessly via other means? I'm looking at using jupyter_client but for now that seems to be even more confusing.

UPDATE:

The io.capture_output context manager seems to be the way to go but I've been able to capture string outputs only (pretty much the same as using %%capture cell magic):

with io.capture_output() as captured:
    result = shell.run_cell(cell)
#captures strings only:

captured.stdout = {str} '<matplotlib.figure.Figure at 0x4f486d8>'
Alex Bausk
  • 690
  • 5
  • 29
  • 1
    'Inline' plots are sent as a display data message to the frontend. So to use them, you need to have a frontend running a separate kernel process. This is what jupyter_client does. Have a look at nbconvert's [ExecutePreprocessor](https://github.com/jupyter/nbconvert/blob/master/nbconvert/preprocessors/execute.py) to see how to use it. – Thomas K May 10 '16 at 16:44
  • Thank you! Your comment suggests using jupyter_client and this is probably the relevant part of ExecutePreprocessor: `msg = self.kc.iopub_channel.get_msg(timeout=4)`. So this is essentially not possible with InteractiveShell? – Alex Bausk May 11 '16 at 08:34
  • Update: I found a `io.capture_output` context manager in the IPython API for handling IOpub channel and managed to capture output using it (see edit in the post), but strings only. Is it possible to do the job with this context manager and if yes, how? Could not find any examples. – Alex Bausk May 11 '16 at 10:03
  • 1
    When you use `InteractiveShell`, there is no iopub channel, so it can't be captured. Iopub and `%matplotlib inline` are specifically kernel features, so you have to run IPython as a Jupyter kernel to use them. – Thomas K May 11 '16 at 10:11
  • Thanks again for your answers. I seem to have found a temporary solution with InteractiveShell. `capture_output()` context manager does the trick and I can retrieve both text/plain and image/png data types from the result. I'm sure this omits a lot of more nuanced stuff with IPython's architecture but this will solve my issue for now. From what I can see inspecting Notebook source code, `_handle_iopub_message` that does rich display processing receives basically the same information as capture_output(). I will answer the question with this result. – Alex Bausk May 12 '16 at 18:51
  • Huh, fair enough. I'm surprised that works. – Thomas K May 13 '16 at 15:04

0 Answers0