如何覆盖 ipython displayhook?

use*_*190 5 python ipython

我已经定义了我自己的显示钩子,它继承自 IPython.core.displayhook.DisplayHook。

我无法在网上找到任何关于覆盖 IPython shell 显示钩子的正确方法的资源。目前,我在 ~/.ipython/profile_default/startup/imports.py 中执行以下操作:

ipyShell = IPython.get_ipython()
ipyShell.displayhook = MyDisplayHook(shell=ipyShell)
ipyShell.displayhook_class = MyDisplayHook
sys.displayhook = ipyShell.displayhook
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为在 ipython shell 启动后, sys.displayhook 以某种方式切换回常规 ipython 显示钩子:

In [5]: print sys.displayhook
<IPython.core.displayhook.DisplayHook object at 0x7f1491853610>
Run Code Online (Sandbox Code Playgroud)

谢谢。

Sil*_*ron 2

万一有人偶然发现了这一点(就像我一样),与标准的 python displayhook 相比,格式化 IPython 的方式实际上乍一看可能会产生误导。

在这个答案中,我尝试首先详细说明 IPython 的不同部分以进行澄清,然后在最后解决 OP(和我的)的具体问题。

在 IPython 中,您可以自定义几乎所有内容,只需使用与标准 python 相差甚远的方法displayhook

IPython 中所谓的“hooks”(请参阅​​文档此示例)实际上旨在改变 shell 的行为。

或者可以更改编辑器的外观,即

In [5]: def foo():
   ...:     return 'foo'
   ...:
Run Code Online (Sandbox Code Playgroud)

接口,特别是In [5]:...:部分。为此,您可以查看IPython 文档,了解如何使用Prompts.

最终,为了改变 python 对象的输出的格式化方式,我必须使用 IPython格式化程序(参见源代码)和此处定义的漂亮打印函数。

例如,如果您想更改默认dict格式

{'axon_angle': 305.010625458 degree,
 'observables': ['length',
   'num_growth_cones'],
 'random_rotation_angles': True}
Run Code Online (Sandbox Code Playgroud)

{
  'axon_angle'            : 305.010625458 degree,
  'observables'           : [
    'length',
    'num_growth_cones',
  ],
  'random_rotation_angles': True
}
Run Code Online (Sandbox Code Playgroud)

你可以使用类似的东西

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)
Run Code Online (Sandbox Code Playgroud)