Search code examples
pythonipythonstdoutread-eval-print-loop

Override REPL output


I'm looking for a way to override and parse all output in Python REPLs: eg python/IPython in a terminal, qtconsole.

This is straightforward for printed text, by overriding the print function. For a trivial example, say we would like to add an exclamation point to all output:

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

Now all print commands will have the added exclamation point. This can be reset with:

del print

My question: How do I do the equivalent for REPL output? For example, how can I make it so this will work?

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

Searches have led me down the path of contextlib, subprocess and sys.stdout, but I've yet to find a solution. Have examined sympy's printing module at Github, without success.


Solution

  • I just tried overwriting sys.stdout.write and it worked (with a few quirks). Someone will correct me if I'm wrong, but I think it's not gonna get much better than this.

    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]:
    

    EDIT:
    I've gotten this far. Haven't figured out where that 1 extra ! comes from.

    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]: