覆盖REPL outpu

2024-04-19 01:19:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找一种方法来覆盖和解析Python REPLs中的所有输出:例如终端qtconsole中的Python/IPython。你知道吗

通过重写print函数,这对于打印文本来说是很简单的。举个简单的例子,假设我们想在所有输出中添加一个感叹号:

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

现在所有的print命令都会添加感叹号。可通过以下方式重置:

del print

我的问题是:如何对REPL输出进行等价处理?例如,我怎样才能让它工作?你知道吗

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

搜索使我走上了contextlib、subprocess和系统标准输出,但我还没有找到解决办法。在Github上检查了sympy的打印模块,但没有成功。你知道吗


Tags: 方法lambda函数text文本命令终端ipython
2条回答

在ipythonqtconsole中基于this article工作的示例。这与OrangeLink的解决方案覆盖标准输出结合使用:

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)

我刚刚试着重写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]:

相关问题 更多 >