日志记录 python 模块的堆栈溢出

Stack overflow on logging python module

我在使用 python 时遇到问题 3,我正在尝试将 stdout 和 stderr 记录到日志文件中。我能够使用 http://www.electricmonk.nl/log/2011/08/14/redirect-stdout-and-stderr-to-a-logger-in-python/

来解决这个问题

重点是让日志文件和控制台输出正常,同时仅使用打印语句。 (我知道这不是你应该做的,我正在尝试记录别人的代码)

我想到了这个:

import logging
import sys
import traceback

class StreamToLogger(object):

    def __init__(self, logger, log_level, std):
        self.logger = logger
        self.log_level = log_level
        self.linebuf = ''
        self.std = std

    def write(self, buf):
        for line in buf.rstrip().splitlines():
            self.logger.log(self.log_level, line.rstrip())
            self.std.write(line+"\n")
            self.std.flush()

    def flush(self):
        return

logging.basicConfig(
   level=logging.DEBUG,
   format='%(asctime)s:%(levelname)s:%(name)s:%(message)s',
   filename="history.log",
   filemode='a'
)

stdout_logger = logging.getLogger('STDOUT')
sl = StreamToLogger(stdout_logger, logging.INFO, sys.__stdout__)
sys.stdout = sl

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

try:
    import bot
    #program that I am logging
except Exception as e:
    traceback.print_exc()
    sys.exit(1)

这很好用,直到日志文件变得太大而无法处理。

所以我的想法是使用旋转日志文件。不幸的是,我想出的旋转日志文件的实现在程序第一次打印任何内容后立即导致堆栈溢出。

这是新代码:

import logging
import sys
import traceback
import logging.handlers

class StreamToLogger(object):

    def __init__(self, logger, log_level, std, handler):
        self.handler = handler
        self.logger = logger
        self.log_level = log_level
        self.linebuf = ''
        self.std = std

    def write(self, buf):
        for line in buf.rstrip().splitlines():
            self.handler.emit(line)
            #^^STACK OVERFLOW^^
            self.logger.log(self.log_level, line.rstrip())
            self.std.write(line+"\n")
            self.std.flush()

    def flush(self):
        return


hand = logging.handlers.TimedRotatingFileHandler("bot.log", when="S", interval=20)
#my attempt at handling


stdout_logger = logging.getLogger('STDOUT')
sl = StreamToLogger(stdout_logger, logging.INFO, sys.__stdout__, hand)
sys.stdout = sl

stderr_logger = logging.getLogger('STDERR')
sl = StreamToLogger(stderr_logger, logging.ERROR, sys.__stderr__, hand)
sys.stderr = sl

try:
    import bot
except Exception as e:
    traceback.print_exc()
    sys.exit(1)

任何人有任何可以提供帮助的想法吗?

我发现了错误,实际上 emit 是由记录器调用的,所以你只需要使用 streamlogger.addHandler 添加处理程序。

更新后的代码

__author__ = 'Girish'

import logging
import sys
import traceback
import logging.handlers


class StreamToLogger(object):
    def __init__(self, logger, log_level, std):

        self.logger = logger
        self.log_level = log_level
        self.linebuf = ''
        self.std = std

    def write(self, buf):
        for line in buf.rstrip().splitlines():
            # ^^STACK OVERFLOW^^
            self.logger.log(self.log_level, line.rstrip())
            self.std.write(line + "\n")
    def flush(self):
        self.std.flush()


logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s:%(levelname)s:%(name)s:%(message)s',
    filename="history.log",
    filemode='a'
)
hand = logging.handlers.TimedRotatingFileHandler("bot.log", when="S", interval=20)
# my attempt at handling


stdout_logger = logging.getLogger('STDOUT')

sl = StreamToLogger(stdout_logger, logging.INFO, sys.__stdout__)

stderr_logger = logging.getLogger('STDERR')
stderr_logger.addHandler(hand) #here

sl = StreamToLogger(stderr_logger, logging.ERROR, sys.__stderr__)
sys.stdout = sl
for i in range(2):
    sl.write("is this working")