记录python模块上的堆栈溢出

时间:2015-03-07 20:13:14

标签: python logging rotation handler stack-overflow

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

来解决这个问题

关键是要同时使用日志文件和控制台输出,而只使用print语句。 (我知道你不应该怎么做,我试图记录别人的代码)

我想出了这个:

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)

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

1 个答案:

答案 0 :(得分:0)

我发现了错误,实际上记录器调用了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")