5

i would like to be able to run a jupyter notebook as a regular python file (using a standard python interpreter) as well. the problem i'm facing is that in python i can not render markdown objects in a usable from:

running the code below renders as it should in the notebook but prints <IPython.core.display.Markdown object> in the when run using just python.

from IPython.display import Markdown, display
display(Markdown('# Hello World!'))

i was trying to come up with a way to make that work and found this ugly work-around:

from IPython.display import Markdown, display
from IPython import get_ipython
from IPython.core.displaypub import DisplayPublisher
from ipykernel.zmqshell import ZMQDisplayPublisher

display_pub_class = get_ipython().display_pub_class()

def displaymd(strg):
    if isinstance(display_pub_class, ZMQDisplayPublisher):
        display(Markdown(strg))
    elif isinstance(display_pub_class, DisplayPublisher):
        print(strg)
    else:
        # ??
        display(strg)

displaymd('# Hello World!')

that seems very hacky! is there a simpler way to get a reasonable display of markdown objects? or at least a simpler way to know whether display is capable of rendering markdown?

the same question goes for latex, html and similar objects.


just found out a silghtly simpler way to check if i am on ipython:

def on_ipython():
    if 'get_ipython' in globals():
        return True
    else:
        return False

def displaymd(strg):
    if on_ipython():
        display(Markdown(strg))
    else:
        print(strg)

still this is not very nice...

hiro protagonist
  • 44,693
  • 14
  • 86
  • 111

1 Answers1

4

Option 1: dicts with both 'text/plain' and 'text/markdown' entries

You can pass a dict containing different MIME types to IPython's display(..., raw=True): Jupyter Notebook will use the rich representation, and an IPython or plain Python frontend will fall back to the text/plain representation.

Here's a minimal complete example; try running it in an IPython terminal and in a Jupyter notebook, and you'll see it renders properly in both.

from IPython.display import display


my_markdown_string = '''\
# Heading one

This is

* a
* list
'''

display({'text/plain': my_markdown_string,
         'text/markdown': my_markdown_string},
        raw=True)

Option 2: Define a custom text/plain formatter for objects of class Markdown

Example is based on the 'define a new int formatter' example from the IPython display docs. You'll want to run it in IPython to see its effect.

from IPython.display import display, Markdown

def md_formatter(md, pp, cycle):
    pp.text(md.data)

text_plain = get_ipython().display_formatter.formatters['text/plain']
text_plain.for_type(Markdown, md_formatter)

display(Markdown('x **x** x'))
# x **x** x

del text_plain.type_printers[Markdown]
display(Markdown('x **x** x'))
# <IPython.core.display.Markdown object>

Appendix: list of MIME types Jupyter/IPython knows about

Taken from the DisplayFormatter docs:

See the display_data message in the messaging documentation for more details about this message type.

The following MIME types are currently implemented:

  • text/plain
  • text/html
  • text/markdown
  • text/latex
  • application/json
  • application/javascript
  • image/png
  • image/jpeg
  • image/svg+xml
Esteis
  • 4,669
  • 2
  • 29
  • 45