在Python日志模块中抑制换行
我正在尝试用Python的日志模块来替换一个临时的日志系统。我使用这个日志系统在一行上输出一个长任务的进度信息,这样你就可以用tail
命令查看日志,或者在控制台中观察它。我是通过在我的日志函数上设置一个标志,来抑制该日志消息的换行符,然后一点一点地构建这一行。
所有的日志记录都是在一个线程中完成的,所以没有串行化的问题。
这样做在Python的日志模块中可行吗?这样做是个好主意吗?
5 个回答
在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(...)
,所以如果你使用了多个日志类,这个补丁也会影响到其他的日志类哦!
想了解更多,可以看看这些链接:
希望这对你有帮助。
如果你想这样做,可以改变日志处理器的结束符。我现在用的是Python 3.4。这个功能是在Python 3.2中引入的,正如Ninjakannon所说的。
handler = logging.StreamHandler()
handler.terminator = ""
当StreamHandler写入内容时,它会最后写入结束符。
我们先来看看你最后的问题:不,我觉得这不是个好主意。这样做会让日志文件在长时间使用后变得难以阅读。
我建议你还是使用logging模块,并在你的'tail'命令中加上'-f'选项,这样可以实时查看控制台的输出。你可能最终会用到FileHandler。注意,'delay'这个参数默认是False,这意味着输出不会被缓存。
如果你真的需要去掉换行符,我建议你自己创建一个Handler。