简体   繁体   English

将 STDOUT 和 STDERR 重定向到 python 记录器和 jupyter notebook

[英]Redirect STDOUT and STDERR to python logger and also to jupyter notebook

Important to know: I am working on jupyter notebook.重要提示:我正在研究 jupyter notebook。

I want to create a logger to which I will redirect the STDOUT and STDERR but I also want to see those outputs on the jupyter notebook output console.我想创建一个记录器,我会将 STDOUT 和 STDERR 重定向到该记录器,但我也想在 jupyter notebook 输出控制台上看到这些输出。

So far what I have implemented is:到目前为止,我已经实施的是:

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

First Question: The previous code, if stored on a .py file, is able to redirect the stdout and stderr to the my_log.log file.第一个问题:前面的代码,如果存储在.py文件中,能够将stdoutstderr重定向到my_log.log文件。 But I lose track of the messages in a normal terminal console.但是我在普通终端控制台中丢失了消息。

What I would like is to have both the stderr and stdout redirected to the log file and also be able to see them on the console.我想要的是将stderrstdout 都重定向到日志文件,并且还能够在控制台上看到它们。

Second Question: I am working on jupyter notebooks and I would like to be able to log from there.第二个问题:我正在处理 jupyter 笔记本,我希望能够从那里登录。 This means all the stdout and stderr redirected from jupyter notebook output to the log file, but also keep it on the jupyter notebook console.这意味着所有 stdout 和 stderr 从 jupyter notebook 输出重定向到日志文件,但也将其保留在 jupyter notebook 控制台上。 I realized that the code above, redirects the stdout to the log file but not the stderr, and as a result all my prints('XX') are in my log file and my exceptions are still on the notebook console.我意识到上面的代码将标准输出重定向到日志文件而不是标准错误,因此我所有的打印('XX')都在我的日志文件中,而我的异常仍然在笔记本控制台上。

Seems like jupyter notebooks deals in a different way with STDOUT and STDERR似乎 jupyter notebooks 以不同的方式处理 STDOUT 和 STDERR

**在此处输入图片描述**

Thanks for your help谢谢你的帮助

It might be a little late.可能有点晚了。
I had similar demands and the best way I can find to do it is something similar to the following code.我有类似的要求,我能找到的最好方法是类似于以下代码。 I use it to track outputs of model training that will run for days.我用它来跟踪将运行数天的模型训练的输出。 It can log to a file by calling Std2File.enable(file_name) and rollback by calling Std2File.disable() .它可以记录通过调用文件Std2File.enable(file_name)并通过调用回滚Std2File.disable() It can log to the file and show it to the notebook.它可以登录到文件并将其显示给笔记本。 the only shortness is that the output displayed on the notebook will always show in the cell of calling enable .唯一的缺点是笔记本上显示的输出将始终显示在调用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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM