为什么日志出现无限循环?

2 投票
1 回答
2224 浏览
提问于 2025-04-15 12:09

我有以下代码:

#!/usr/bin/env python
import logging
import sys
import copy

class Wrapper:
    def write(self, s):
        #sys.__stdout__.write(s)
        loggy = logging.getLogger('foobar')
        loggy.info(s)

def blah():
    logger = logging.getLogger('foobar')
    logger.setLevel(logging.DEBUG)
    streamhandle = logging.StreamHandler(sys.stdout)
    streamhandle.setFormatter(logging.Formatter('[%(message)s]'))
    logger.addHandler(streamhandle)

    sys.stdout = Wrapper()
    sys.stderr = Wrapper()

if __name__ == '__main__':

    blah()
    logger = logging.getLogger('')
    #print logger.handlers
    #for handler in logger.handlers:
    #    print handler

    fooy = logging.getLogger('foobar')
    #print fooy.handlers

    sys.stdout.write('i love you')

    logging.log(logging.DEBUG, 'i love you')

这段代码让Python陷入了一个无限递归的循环,输出结果实际上非常酷:

[Error in sys.exitfunc:
]
[INFO:foobar:Error in sys.exitfunc:

]
[INFO:foobar:INFO:foobar:Error in sys.exitfunc:


]
[INFO:foobar:INFO:foobar:INFO:foobar:Error in sys.exitfunc:



]
[INFO:foobar:INFO:foobar:INFO:foobar:INFO:foobar:Error in sys.exitfunc:




]
[INFO:foobar:INFO:foobar:INFO:foobar:INFO:foobar:INFO:foobar:Error in sys.exitfunc:

这个输出会以指数级的速度增长 :) 看起来很漂亮,但这是为什么呢?

1 个回答

6

这个无限循环发生的原因是因为你的记录器(logger)的 StreamHandler 被设置为将日志信息写入 sys.stdout,而 sys.stdout 又被包装起来,结果又写回到刚刚发送写入信息的那个记录器。

根据你的需求,可能更好的是让 Wrapper 直接进行输出,而不是在内部使用日志记录。可以考虑这样做:

class Wrapper(object):
    def write(self, s):
        sys.__stdout__.write(s) # sys.__stdout__ points to the original stdout, rather
                                # than the redirected sys.stdout

撰写回答