【问题标题】:Redirect STDOUT and STDERR to python logger and also to jupyter notebook将 STDOUT 和 STDERR 重定向到 python logger 和 jupyter notebook
【发布时间】:2020-06-02 12:24:45
【问题描述】:

重要提示:我正在研究 jupyter notebook。

我想创建一个记录器,将 STDOUT 和 STDERR 重定向到该记录器,但我也想在 jupyter notebook 输出控制台上查看这些输出。

到目前为止我已经实现的是:

import logging
import sys

class StreamToLogger(object):
    """
    Fake file-like stream object that redirects writes to a logger instance.
    """
    def __init__(self, logger, log_level=logging.INFO):
        self.logger = logger
        self.log_level = log_level
        self.linebuf = ''

    def write(self, buf):
        for line in buf.rstrip().splitlines():
            self.logger.log(self.log_level, line.rstrip())

    def flush(self):
        pass

logging.basicConfig(filename='my_log.log',
                    filemode='a',
                    # stream=sys.stdout,
                    level=logging.DEBUG,
                    format='%(asctime)s;%(name)s;%(levelname)s;%(message)s')

# redirect stdout and stderr to logger
stdout_logger = logging.getLogger('STDOUT')
sl = StreamToLogger(stdout_logger, logging.INFO)
sys.stdout = sl

stderr_logger = logging.getLogger('STDERR')
s2 = StreamToLogger(stderr_logger, logging.ERROR)
sys.stderr = s2

log = logging.getLogger('my_log')

# An info log
log.info('This is an info')

# A stdout message
print("This is an STDOUT")

# A stderr message
1 / 0

第一个问题: 前面的代码,如果存储在 .py 文件中,可以将 stdoutstderr 重定向到 my_log.log 文件。但是我在普通终端控制台中忘记了消息。

我希望将 stderrstdout 都重定向到日志文件,并且能够在控制台上看到它们。

第二个问题: 我正在研究 jupyter 笔记本,我希望能够从那里登录。这意味着所有 stdout 和 stderr 都从 jupyter notebook 输出重定向到日志文件,但也将其保留在 jupyter notebook 控制台上。 我意识到上面的代码将标准输出重定向到日志文件而不是标准错误,因此我所有的打印('XX')都在我的日志文件中,我的异常仍然在笔记本控制台上。

似乎 jupyter notebooks 以不同的方式处理 STDOUT 和 STDERR

感谢您的帮助

【问题讨论】:

  • 您是否特别需要 stdout 和 stderr 在它们运行的​​单元格的输出中显示?如果没有,您需要的大部分内容已经由 Jupyter 笔记本 %%capture 单元魔术命令处理,请参阅 here。例如,%%capture out 创建一个 utils.io.CapturedIO 对象,您可以访问不同的属性,例如 out.stdout 并根据需要进行处理。使用它,在下一个单元格中,您可以将您想要的内容发送到日志文件,然后也可以在笔记本输出中打印输出。
  • 另请参阅 io.capture_output() here 以选择性地仅对单元格中运行的代码的某些部分使用捕获。
  • 还有 JupyterLab 记录器/日志控制台,见here
  • 感谢您的帮助@Wayne。我现在正在尝试使用魔术命令和 IPython.utils.io.capture_output,它适用于标准输出,但不适用于标准错误。有任何想法吗?我将 Ipython 的版本更新到 7.12...
  • 我刚刚在 Jupyter(笔记本和 JupyterLab 界面)和 IPython 中测试了 %%capture out,我能够分别查看这两个流。 out.stdout 显示 print 语句中的内容,out.stderr 显示来自 sys.stderr.write() 的内容。

标签: python logging jupyter-notebook stdout stderr


【解决方案1】:

可能有点晚了。
我有类似的要求,我能找到的最好方法是类似于以下代码。我用它来跟踪将运行数天的模型训练的输出。它可以通过调用Std2File.enable(file_name) 记录到文件并通过调用Std2File.disable() 进行回滚。 它可以记录到文件并将其显示到笔记本上。唯一不足的是笔记本上显示的输出将始终显示在调用enable的单元格中。


class Std2File(object):
    """
    Redirect stoout and stderr to a local file.
    It is designed for use case of notebook where after you close a notebook you can record the stdout and stderr
    """
    stdout = None
    stderr = None
    fd = None

    def __init__(self, f, std):
        self.std = std
        self.f = f

    @staticmethod
    def enable(f='/tmp/std_copy.log'):
        if Std2File.stdout is None:
            Std2File.stdout = sys.stdout
            Std2File.stderr = sys.stderr
            Std2File.fd = open(f, 'a+')
            sys.stdout = Std2File(Std2File.fd, sys.stdout)
            sys.stderr = Std2File(Std2File.fd, sys.stderr)
        print('\n\nbackup stdout/stderr to %s at %s\n' % (f, dt.datetime.now()))

    @staticmethod
    def disable():
        if Std2File.stdout is not None:
            sys.stdout = Std2File.stdout
            sys.stderr = Std2File.stderr
            Std2File.stderr = Std2File.stdout = None
            Std2File.fd.close()
            Std2File.fd = None

    def __getattr__(self, name):
        return object.__getattribute__(self.f, name)

    def write(self, x):
        self.std.write(x)
        self.std.flush()
        self.f.write(x)
        self.f.flush()

    def flush(self):
        self.std.flush()
        self.f.flush()

【讨论】:

    猜你喜欢
    • 2014-07-22
    • 2012-08-07
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2011-05-23
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多