How do I construct a python function where the input in python code and output is ipython rich output (in HTML)?

Question:

How do I construct a function foo() such that

pycode = '''
from matplotlib import pyplot as plt
plt.plot([1, 2, 3])
plt.show()
'''

out = foo(pycode)

where out is the rich text HTML output that ipython or jupyter notebook would output

Is there some inbuilt function in ipython that can do this? I would guess there is but I couldn’t find it anywhere googling.

Edit: I want the function to exist in my python script, not when I am running ipython shell

Edit: What I want to do is to essentially recreate something like a jupyter notebook cell where I give it the code and It return the rich outputs visually (perhaps in HTML form) like a jupyter notebook cell would.

Asked By: Julian Chu

||

Answers:

I think you are looking for Python’s exec() method?

In a JupyterLab where matplotlib is installed, you can run this in a cell and see the output below it:

pycode = '''
from matplotlib import pyplot as plt
plt.plot([1, 2, 3])
plt.show()
'''
out = exec(pycode)

Keep in mind that use of exec(), and the related eval(), are generally discouraged. Their use can potentially enable others, or even you unwittingly, execute code you didn’t mean to run that can cause severe problems. Often, their use is unnecessary if you use proper methods, see here. (Seems you can even do it using WebAssembly-based Python now, see PyScript: is it possible to execute an uploaded Python script?.)


UPDATE IN RESPONSE TO FIRST COMMENT:

As written, out wasn’t collecting anything despite the code working to make the plot because exec(pycode) happened to be on last line. There is a way to collect the RichOutput when running it using IPython’s capture utilities. And because it works via imports, it will work in Python, if you have the Jupyter/IPython ecosystem installed there as well. In other words although I am demonstrating it in a notebook, you can make a function to use return captured.outputs[0] and it will return the RichOutput from the plotting.

See the underlying reasoning more fleshed out in this notebook here with some other examples of importing IPython into Python that can also be done in Python scripts entirely separate from Jupyter.

Note because I deal with RichOutput and making images, you’ll also want to see the references therein. There’s a lot more in there that I’m not touching on.

pycode = ''' 
from matplotlib import pyplot as plt
fig = plt.figure()
plt.plot([1, 2, 3])
plt.show()
'''
from IPython.utils import io
with io.capture_output() as captured:
    exec(pycode)
fig.savefig("after_the_fact_save.png")

Making a simple function & not using exec()

See programmatically making a .py file in the example notebook here. Normally, you could such a file in your text editor by writing saving the text by hand, such as the following saved as plot_func.py:

def my_plot_func():
    from matplotlib import pyplot as plt
    plt.plot([1, 2, 3])
    plt.savefig('my_plot_via_func.png')

Then that is imported and run. Part of the process saves an image of the file. In the notebook, that image file my_plot_via_func.png is displayed.

This is the simplistic version. The importing and executing the function will work in pure Python run in a terminal, or elsewhere, in the same way, up to displaying the image file. If you returned the plot as a plot object (figure) you’d need some way to display. That works in Jupyter, but not in pure Python.

I added this because I am still unclear what you want to do. I have a way more advanced version of that where you supply a specially organized Pandas dataframe and get a specialized plot back. To try it go here and press launch binder and work through the example notebook that comes up when the sessions starts. Perhaps that will help you better formulate asking about what you seek. Especially since it takes something much like this plotting script with everything hardcoded and generalizes it to make a version where it is a command line script or a function you can call. You’ll see the infrastructure I was saying is necessary in my comment below. The command line script runs with pure python, too. You’ll see I use %run generally in the notebook because that is more full-featured; however, in the notebook you can generally substitute !python for %run if you can sacrifice better output handling and don’t need to run the script in the notebook namespace like %run -i allows.

For an example of using matplotlib plotting to make code that returns a specialized plot by another person, see here.


Generating HTML

The OP wanted HTML, and I’ve added a section where HTML is generated to the bottom of the main example notebook here, that was in response to the first comment. In fact, this post ‘Imbed [sic] matplotlib figure into iPython HTML’ may have covered much of what the OP wanted?

Answered By: Wayne
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.