首页 > 解决方案 > iPython,保存代码单元的输出并在执行期间仍然正常显示输出

问题描述

所以,这个问题的通常答案是使用单元格魔术“%%caputre cap”,问题是它抑制了正常输出并显示它你必须在执行单元格后运行“cap.show()” . 当运行一个需要很长时间的单元时,比如训练一个神经网络,这个特性会成为一个令人头疼的问题。我怎样才能像往常一样运行我的代码单元并获得实时输出,然后才能将其保存到 .txt 文件中?

标签: pythonoutputipythoncell

解决方案


这不是 IPython/Jupyter 特定的,但这是我为类似目的编写的上下文管理器:

import sys


class capture_stdout:
    """
    Context manager similar to `contextlib.redirect_stdout`, but
    different in that it:
      - temporarily writes stdout to other streams *in addition to*
        rather than *instead of* `sys.stdout`
      - accepts any number of streams and sends stdout to each
      - can optionally keep streams open after exiting context by
        passing `closing=False`

    Parameters
    ----------
    *streams : *`io.IOBase`
        stream(s) to receive data sent to `sys.stdout`

    closing : `bool`, optional
        if [default: `True`], close streams upon exiting the context
        block.
    """
    def __init__(self, *streams, closing=True):
        self.streams = streams
        self.closing = closing
        self.sys_stdout_write = sys.stdout.write

    def __enter__(self):
        sys.stdout.write = self._write
        if len(self.streams) == 1:
            return self.streams[0]
        return self.streams

    def __exit__(self, exc_type, exc_value, traceback):
        sys.stdout.write = self.sys_stdout_write
        if self.closing:
            for s in self.streams:
                s.close()

    def _write(self, data):
        for s in self.streams:
            s.write(data)
        self.sys_stdout_write(data)
        sys.stdout.flush()

您可以通过任意数量的流,它会实时写入常规之外的所有流。sys.stdout因此,例如,如果您想显示实时输出,将其捕获以供稍后在代码中使用,并将其记录到文件中,您可以执行以下操作:

from io import StringIO


with capture_stdout(StringIO(), open('logfile.txt', 'w')) as (mem_stream, file_stream):
    print('some really long output')
    # etc...
    stdout = mem_stream.getvalue()
    

print(f"in str: {stdout}")
with open('logfile.txt', 'r') as f:
    print(f"in file: {f.read()}")
some really long output

in str: some really long output

in file: some really long output

变成一个以同样方式工作的细胞魔法也不应该太难。 如果你想试一试,这里是关于定义自定义魔法的文档部分。IPython


推荐阅读