我正在尝试用Python的日志记录模块替换ad-hoc日志记录系统。我正在使用日志记录系统在单行上输出长任务的进度信息,因此您可以tail
日志或在控制台中查看日志。我已经通过在我的日志记录功能上设置一个标志来完成此操作,该标志会抑制该日志消息的换行符并逐段构建该行。
所有日志记录都是从一个线程完成的,所以没有序列化问题。
是否可以使用Python的日志记录模块执行此操作?这是个好主意吗?
答案 0 :(得分:34)
如果要执行此操作,可以更改日志记录处理程序终止符。我正在使用Python 3.4。这是在Ninjakannon所说的Python 3.2中引入的。
handler = logging.StreamHandler()
handler.terminator = ""
当StreamHandler写入时,它最后写终止符。
答案 1 :(得分:12)
新行\n
已插入StreamHandler
类。
如果您真的设置了 fix 这种行为,那么这里是一个示例,说明我是如何通过monkey patching 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 ,或者其他什么。可能是这样,所以要小心。
另外,请注意这将全局修补SteamHandler.emit(...)
,因此如果您使用多个日志记录类,那么此修补程序也会影响其他日志记录类!
查看这些内容以供进一步阅读:
希望有所帮助。
答案 2 :(得分:8)
让我们从你的上一个问题开始:不,我不相信这是个好主意。 IMO,从长远来看,它会损害日志文件的可读性。
我建议坚持使用logging模块并使用'tail'命令中的'-f'选项来监视控制台的输出。您最终可能会使用FileHandler。请注意,'delay'的默认参数为False,这意味着输出不会被缓冲。
如果确实需要禁止换行,我建议您创建自己的处理程序。
答案 3 :(得分:0)
在遍历元组时,我遇到了在一行中记录某个部分的需要,但是我想保留整个记录器。
首先将输出收集到一个字符串中,然后在我离开本节之后将其发送到记录器。概念示例
for fld in object._fields:
strX = (' {} --> {} ').format(fld, formattingFunction(getattr(obj,fld)))
debugLine += strX
logger.debug('{}'.format(debugLine))
答案 4 :(得分:0)
Python 3.5.9
class MFileHandler(logging.FileHandler):
"""Handler that controls the writing of the newline character"""
special_code = '[!n]'
def emit(self, record) -> None:
if self.special_code in record.msg:
record.msg = record.msg.replace( self.special_code, '' )
self.terminator = ''
else:
self.terminator = '\n'
return super().emit(record)
然后
fHandler = MFileHandler(...)
示例:
# without \n
log.info( 'waiting...[!n]' )
...
log.info( 'OK' )
# with \n
log.info( 'waiting...' )
...
log.info( 'OK' )
log.txt:
waiting...OK
waiting...
OK