在Python日志模块中抑制换行

63 投票
5 回答
59428 浏览
提问于 2025-04-17 00:14

我正在尝试用Python的日志模块来替换一个临时的日志系统。我使用这个日志系统在一行上输出一个长任务的进度信息,这样你就可以用tail命令查看日志,或者在控制台中观察它。我是通过在我的日志函数上设置一个标志,来抑制该日志消息的换行符,然后一点一点地构建这一行。

所有的日志记录都是在一个线程中完成的,所以没有串行化的问题。

这样做在Python的日志模块中可行吗?这样做是个好主意吗?

5 个回答

13

StreamHandler类里面插入了一个换行符\n

如果你真的想要修复这个行为,这里有个例子,展示我怎么通过猴子补丁的方式,修改logging.StreamHandler类里的emit(self, record)方法。

猴子补丁是一种在不改变原始源代码的情况下,扩展或修改动态语言运行时代码的方法。这个过程也被称为鸭子打补丁。

下面是一个自定义的emit()实现,它省略了换行:

def customEmit(self, record):
    # Monkey patch Emit function to avoid new lines between records
    try:
        msg = self.format(record)
        if not hasattr(types, "UnicodeType"): #if no unicode support...
            self.stream.write(msg)
        else:
            try:
                if getattr(self.stream, 'encoding', None) is not None:
                    self.stream.write(msg.encode(self.stream.encoding))
                else:
                    self.stream.write(msg)
            except UnicodeError:
                self.stream.write(msg.encode("UTF-8"))
        self.flush()
    except (KeyboardInterrupt, SystemExit):
        raise
    except:
        self.handleError(record)

接着你需要创建一个自定义的日志类(在这个例子中,是从TimedRotatingFileHandler继承的)。

class SniffLogHandler(TimedRotatingFileHandler):
    def __init__(self, filename, when, interval, backupCount=0,
                 encoding=None, delay=0, utc=0):

        # Monkey patch 'emit' method
        setattr(StreamHandler, StreamHandler.emit.__name__, customEmit)

        TimedRotatingFileHandler.__init__(self, filename, when, interval,
                                          backupCount, encoding, delay, utc)

有些人可能会说这种解决方案不够Pythonic,或者其他什么的。可能确实如此,所以要小心。

另外,要注意这会全局修改StreamHandler.emit(...),所以如果你使用了多个日志类,这个补丁也会影响到其他的日志类哦!

想了解更多,可以看看这些链接:

希望这对你有帮助。

73

如果你想这样做,可以改变日志处理器的结束符。我现在用的是Python 3.4。这个功能是在Python 3.2中引入的,正如Ninjakannon所说的。

handler = logging.StreamHandler()
handler.terminator = ""

当StreamHandler写入内容时,它会最后写入结束符。

17

我们先来看看你最后的问题:不,我觉得这不是个好主意。这样做会让日志文件在长时间使用后变得难以阅读。

我建议你还是使用logging模块,并在你的'tail'命令中加上'-f'选项,这样可以实时查看控制台的输出。你可能最终会用到FileHandler。注意,'delay'这个参数默认是False,这意味着输出不会被缓存。

如果你真的需要去掉换行符,我建议你自己创建一个Handler。

撰写回答