覆盖REPL输出

问题描述:

我正在寻找一种方法来覆盖和解析Python REPL中的所有输出:例如,终端中的python/IPython,qtconsole。覆盖REPL输出

通过重写打印功能,可以直接打印文本。对于一个简单的例子,假设我们想感叹号添加到所有输出:

orig_print = print 
print = lambda text: orig_print(text + '!') 

现在所有打印命令将有加感叹号。这可以重置为:

del print 

我的问题:如何做REPL输出的等价物?例如,我怎样才能做到这一点?

In[1]: 5 + 5 
Out[2]: 10! 

搜索导致我失望contextlib,子和sys.stdout的路径,但我还没有找到一个解决方案。在Github上检查过sympy的打印模块,但没有成功。

+0

嗯..也许这是可能的'sys.settrace' –

我只是试图覆盖sys.stdout.write它工作(有一些怪癖)。有人会纠正我,如果我错了,但我认为它不会比这更好。

In [1]: import sys 

In [2]: tmp = sys.stdout.write 

In [3]: sys.stdout.write = lambda text: tmp(text + '!') 

In [4]: 5 + 5 
!Out[4]: 10! 
!! 
!!In [5]: 

编辑:
我远远得到这一点。还没有想出那1个额外的!来自哪里。

In [5]: sys.stdout.write = lambda text: tmp(text if text.endswith('\n') else text + '!\r') 

In [6]: 5+5 
Out[6]: 10! 
! 
In [7]: 
+0

这是可能的解决''在下一行来改变'TMP(文本+ '!')'to'tmp(text +'!\ r')' – DeepSpace

+0

对于我的特定用例,这个异常(额外!)没有出现:您的解决方案按原样运行! –

+0

有没有人有关于IPython qtconsole的等价物的想法?它似乎不使用sys.stdout。我试过ipykernel.iostream.OutStream.write和IPython.sys.stdout.write。 –

一个在IPython QtConsole中工作的示例,基于this article。这是配合使用orangeink的解决方案覆盖标准输出:

class SciNum: 
    """For compatibility with IPython's pretty printer: Contains a string, 
    with a REPR that allows pretty() to print without quotes, as it would 
    if using the string directly.""" 
    def __init__(self, text: str): 
     self.text = text 

    def __repr__(self): 
     return self.text 


def _print_ipython(arg, p, cycle) -> None: 
    """Uses IPython's pretty printer to modify output for a qtconsole or notebook; 
    stdout doesn't seem to work for them.""" 
    p.text(IPython.lib.pretty.pretty(SciNum(format(arg)))) 

def start() -> None: 
    if not ipython_exists: 
     return 

    ip = IPython.get_ipython() 
    # We only need to handle IPython separately if in a Qtconsole or Notebook. 
    if isinstance(ip, IPython.terminal.interactiveshell.TerminalInteractiveShell): 
     return 

    text_formatter = ip.display_formatter.formatters['text/plain'] 

    text_formatter.for_type(float, _print_ipython) 
    text_formatter.for_type(int, _print_ipython)