Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override ipython displayhook?

Tags:

python

ipython

I have defined my own displayhook that inherits from IPython.core.displayhook.DisplayHook.

I was unable to find any resources online as for the proper way of overriding the displayhook for an IPython shell. Currently, I am doing the following in ~/.ipython/profile_default/startup/imports.py:

ipyShell = IPython.get_ipython()
ipyShell.displayhook = MyDisplayHook(shell=ipyShell)
ipyShell.displayhook_class = MyDisplayHook
sys.displayhook = ipyShell.displayhook

Which does not work, as after the ipython shell starts up, sys.displayhook is somehow switched back to the regular ipython display hook:

In [5]: print sys.displayhook
<IPython.core.displayhook.DisplayHook object at 0x7f1491853610>

Thanks.

like image 248
user5871190 Avatar asked Nov 21 '22 12:11

user5871190


1 Answers

In case someone stumbles on this (like I did), the way to format IPython can actually be misleading at first glance when compared to the standard python displayhook.

In this answer, I try to detail first the different parts of IPython to clarify, then tackle the specific question of the OP (and mine) at the end.

In IPython, you can customize almost everything, only using methods that are quite far from the standard python displayhook.

What is called "hooks" in IPython (see the doc and this example) is actually something aimed at altering the behavior of the shell.

Alternatively can change how the editor looks like, i.e. the

In [5]: def foo():
   ...:     return 'foo'
   ...:

interface, and specifically the In [5]: and ...: parts. For that, you can have a look at the IPython doc to see how to do that with Prompts.

Eventually, to alter how the output of a python object is formatted, I had to use the IPython formatters (cf. source code) and the pretty printing functions defined here.

For instance, if you want to change the default dict formatting from

{'axon_angle': 305.010625458 degree,
 'observables': ['length',
   'num_growth_cones'],
 'random_rotation_angles': True}

to

{
  'axon_angle'            : 305.010625458 degree,
  'observables'           : [
    'length',
    'num_growth_cones',
  ],
  'random_rotation_angles': True
}

You can use something like

def dict_formatter(obj, p, cycle):
    if cycle:
        return p.text('{...}')
    start = '{'
    end   = '}'
    step = 2
    p.begin_group(step, start)
    keys = obj.keys()
    max_len = 0
    for k, v in obj.items():
        max_len = max(max_len, len(str(k)))

    if obj:
        p.breakable()
    for idx, key in p._enumerate(keys):
        if idx:
            p.text(',')
            p.breakable()
        p.pretty(key)
        wlen = max_len-len(str(key))
        p.text(' '*wlen + ': ')
        p.pretty(obj[key])
    if obj:
        p.end_group(step, '')
        p.breakable()
        p.text(end)
    else:
        p.end_group(step, end)

import IPython
ip = IPython.get_ipython()
formatter = ip.display_formatter.formatters['text/plain']
formatter.for_type(dict, dict_formatter)
like image 69
Silmathoron Avatar answered Dec 05 '22 03:12

Silmathoron