2017-12-18 173 views
1

我正在尋找一種方法來覆蓋和解析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' –

回答

2

我只是試圖覆蓋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。 –

0

一個在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)