25
25
.. note::
26
26
27
27
This module has a few key differences compared to its CPython counterpart, notably
28
- that loggers can only be assigned one handler at a time. Calling ``addHander()``
29
- replaces the currently stored handler for that logger. Additionally, the default
30
- formatting for handlers is different.
28
+ that loggers do not form a hierarchy that allows record propagation.
29
+ Additionally, the default formatting for handlers is different.
31
30
32
31
Attributes
33
32
----------
@@ -275,7 +274,8 @@ def __init__(self, name: Hashable, level: int = WARNING) -> None:
275
274
self .name = name
276
275
"""The name of the logger, this should be unique for proper
277
276
functionality of `getLogger()`"""
278
- self ._handler = None
277
+ self ._handlers = []
278
+ self .emittedNoHandlerWarning = False
279
279
280
280
def setLevel (self , log_level : int ) -> None :
281
281
"""Set the logging cutoff level.
@@ -294,23 +294,40 @@ def getEffectiveLevel(self) -> int:
294
294
return self ._level
295
295
296
296
def addHandler (self , hdlr : Handler ) -> None :
297
- """Sets the handler of this logger to the specified handler.
298
-
299
- *NOTE* This is slightly different from the CPython equivalent
300
- which adds the handler rather than replacing it.
297
+ """Adds the handler to this logger.
301
298
302
299
:param Handler hdlr: The handler to add
303
300
"""
304
- self ._handler = hdlr
301
+ self ._handlers .append (hdlr )
302
+
303
+ def removeHandler (self , hdlr : Handler ) -> None :
304
+ """Remove handler from this logger.
305
+
306
+ :param Handler hdlr: The handler to remove
307
+ """
308
+ self ._handlers .remove (hdlr )
305
309
306
310
def hasHandlers (self ) -> bool :
307
311
"""Whether any handlers have been set for this logger"""
308
- return self ._handler is not None
312
+ return len ( self ._handlers ) > 0
309
313
310
314
def _log (self , level : int , msg : str , * args ) -> None :
311
315
record = _logRecordFactory (self .name , level , msg % args , args )
312
- if self ._handler and level >= self ._level :
313
- self ._handler .emit (record )
316
+ self .handle (record )
317
+
318
+ def handle (self , record : LogRecord ) -> None :
319
+ """Pass the record to all handlers registered with this logger.
320
+
321
+ :param LogRecord record: log record
322
+ """
323
+ if not self .hasHandlers () and not self .emittedNoHandlerWarning :
324
+ sys .stderr .write (f"Logger '{ self .name } ' has no handlers\n " )
325
+ self .emittedNoHandlerWarning = True
326
+ return
327
+
328
+ if record .levelno >= self ._level :
329
+ for handler in self ._handlers :
330
+ handler .emit (record )
314
331
315
332
def log (self , level : int , msg : str , * args ) -> None :
316
333
"""Log a message.
0 commit comments