什么是Handler?
Handler instances dispatch logging events to specific destinations.
其实很简单, Handler决定了你的LogRecord
最终出现的位置, 你的log信息是直接输出到终端(StreamHandler) 还是 保存到 log文件(FileHandler).
Handler是如何记录信息的?
常见的Handler就是我们常用的I/O操作, 类似于我们的print()
以及file.write()
, 以StreamHandler
为例:
class StreamHandler(Handler):
terminator = '\n'
def __init__(self, stream=None):
"""
Initialize the handler.
If stream is not specified, sys.stderr is used.
"""
Handler.__init__(self)
if stream is None:
stream = sys.stderr
self.stream = stream
def emit(self, record):
"""
Emit a record.
"""
try:
msg = self.format(record)
stream = self.stream
stream.write(msg)
stream.write(self.terminator)
self.flush()
except Exception:
self.handleError(record)
log消息的输出是用emit()
函数实现的, 本质就是sys.stderr.write()
, 这样一看logging
模块就非常简单了.
然后我们再看一下FileHandler的 emit()
:
class FileHandler(StreamHandler):
"""
A handler class which writes formatted logging records to disk files.
"""
def __init__(self, filename, mode='a', encoding=None, delay=False):
if delay:
#We don't open the stream, but we still need to call the
#Handler constructor to set level, formatter, lock etc.
Handler.__init__(self)
self.stream = None
else:
StreamHandler.__init__(self, self._open())
def emit(self, record):
"""
Emit a record.
"""
if self.stream is None:
self.stream = self._open()
StreamHandler.emit(self, record)
FileHandler
继承自StreamHandler
, 只是把stream
替换为打开的文件, 所以我们的emit
就变为了file.write()
.
flush()
是做什么用的?
The internal buffers are buffers created by the runtime/library/language that you're programming against and is meant to speed things up by avoiding system calls for every write. Instead, when you write to a file object, you write into its buffer, and whenever the buffer fills up, the data is written to the actual file using system calls.
当我们读写文件, 类似stdout
或者是打开的文件, 我们的数据都在缓存中, flush
保证将缓存中的数据写入文件, 这个操作一般在文件close()
时自动执行.
Thread Safe
类似于读写文件的操作是位于临界区内, 多个线程同时操作会导致race condition
, 所以在读写文件操作时, logging
模块对这些操作进行了加锁:
def flush(self):
"""
Flushes the stream.
"""
self.acquire()
try:
if self.stream and hasattr(self.stream, "flush"):
self.stream.flush()
finally:
self.release()
总结
Handler
作为logging
模块中最常用的class
之一, 通过了解其实现, 能够更好的帮助我们理解logging
模块.