kopia lustrzana https://github.com/micropython/micropython-lib
logging.py: CPython-compatible logging improvements.
This commit allows for logging handlers to be added to the root logger and then used by non-root loggers that don't have their own handlers. It also adds the (CPython-compatible) handlers argument to logging.basicConfig() to ease this initialization: import logging sh = logging.StreamHandler() fh = logging.FileHandler("my.log", mode="a") logging.basicConfig(handlers=[sh, fh]) root_logger = logging.getLogger() # uses sh and fh another_logger = logging.getLogger("another") # inherits handlers It also adds the Logger.removeHandler() method and avoids repeated handler addition. It also adds the flush() method to StreamHandler and its subclasses. It also correctly calls the superclass constructor from the StreamHandler constructor and uses a default formatter if a Handler has none set (as in PR #710). Signed-off-by: Ned Konz <ned@productcreationstudio.com>pull/806/head
rodzic
661efa48f0
commit
94a38ab297
|
@ -25,6 +25,7 @@ _loggers = {}
|
||||||
_stream = sys.stderr
|
_stream = sys.stderr
|
||||||
_default_fmt = "%(levelname)s:%(name)s:%(message)s"
|
_default_fmt = "%(levelname)s:%(name)s:%(message)s"
|
||||||
_default_datefmt = "%Y-%m-%d %H:%M:%S"
|
_default_datefmt = "%Y-%m-%d %H:%M:%S"
|
||||||
|
_default_formatter = None
|
||||||
|
|
||||||
|
|
||||||
class LogRecord:
|
class LogRecord:
|
||||||
|
@ -43,9 +44,19 @@ class Handler:
|
||||||
self.level = level
|
self.level = level
|
||||||
self.formatter = None
|
self.formatter = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _default_formatter():
|
||||||
|
global _default_formatter
|
||||||
|
if _default_formatter is None:
|
||||||
|
_default_formatter = Formatter()
|
||||||
|
return _default_formatter
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def setLevel(self, level):
|
def setLevel(self, level):
|
||||||
self.level = level
|
self.level = level
|
||||||
|
|
||||||
|
@ -53,15 +64,20 @@ class Handler:
|
||||||
self.formatter = formatter
|
self.formatter = formatter
|
||||||
|
|
||||||
def format(self, record):
|
def format(self, record):
|
||||||
return self.formatter.format(record)
|
if self.formatter:
|
||||||
|
fmt = self.formatter
|
||||||
|
else:
|
||||||
|
fmt = self._default_formatter()
|
||||||
|
return fmt.format(record)
|
||||||
|
|
||||||
|
|
||||||
class StreamHandler(Handler):
|
class StreamHandler(Handler):
|
||||||
def __init__(self, stream=None):
|
def __init__(self, stream=None):
|
||||||
|
super().__init__()
|
||||||
self.stream = _stream if stream is None else stream
|
self.stream = _stream if stream is None else stream
|
||||||
self.terminator = "\n"
|
self.terminator = "\n"
|
||||||
|
|
||||||
def close(self):
|
def flush(self):
|
||||||
if hasattr(self.stream, "flush"):
|
if hasattr(self.stream, "flush"):
|
||||||
self.stream.flush()
|
self.stream.flush()
|
||||||
|
|
||||||
|
@ -128,7 +144,7 @@ class Logger:
|
||||||
msg = msg % args
|
msg = msg % args
|
||||||
self.record.set(self.name, level, msg)
|
self.record.set(self.name, level, msg)
|
||||||
handlers = self.handlers
|
handlers = self.handlers
|
||||||
if not handlers:
|
if not self.hasHandlers():
|
||||||
handlers = getLogger().handlers
|
handlers = getLogger().handlers
|
||||||
for h in handlers:
|
for h in handlers:
|
||||||
h.emit(self.record)
|
h.emit(self.record)
|
||||||
|
@ -161,7 +177,13 @@ class Logger:
|
||||||
self.log(ERROR, buf.getvalue())
|
self.log(ERROR, buf.getvalue())
|
||||||
|
|
||||||
def addHandler(self, handler):
|
def addHandler(self, handler):
|
||||||
self.handlers.append(handler)
|
if handler not in self.handlers:
|
||||||
|
self.handlers.append(handler)
|
||||||
|
|
||||||
|
def removeHandler(self, handler):
|
||||||
|
if handler in self.handlers:
|
||||||
|
handler.close()
|
||||||
|
self.handlers.remove(handler)
|
||||||
|
|
||||||
def hasHandlers(self):
|
def hasHandlers(self):
|
||||||
return len(self.handlers) > 0
|
return len(self.handlers) > 0
|
||||||
|
@ -225,17 +247,28 @@ def basicConfig(
|
||||||
stream=None,
|
stream=None,
|
||||||
encoding="UTF-8",
|
encoding="UTF-8",
|
||||||
force=False,
|
force=False,
|
||||||
|
handlers=None,
|
||||||
):
|
):
|
||||||
if "root" not in _loggers:
|
if "root" not in _loggers:
|
||||||
_loggers["root"] = Logger("root")
|
_loggers["root"] = Logger("root")
|
||||||
|
|
||||||
logger = _loggers["root"]
|
logger = _loggers["root"]
|
||||||
|
|
||||||
if force or not logger.handlers:
|
if force:
|
||||||
for h in logger.handlers:
|
for h in logger.handlers:
|
||||||
h.close()
|
h.close()
|
||||||
logger.handlers = []
|
logger.handlers = []
|
||||||
|
|
||||||
|
if len([arg for arg in (filename, stream, handlers) if arg is not None]) > 1:
|
||||||
|
raise ValueError("can only set one of 'filename', 'stream' or 'handlers'")
|
||||||
|
|
||||||
|
if handlers is not None:
|
||||||
|
for h in handlers:
|
||||||
|
if h.formatter is None:
|
||||||
|
h.setFormatter(Formatter(format, datefmt))
|
||||||
|
logger.addHandler(h)
|
||||||
|
|
||||||
|
if not logger.hasHandlers():
|
||||||
if filename is None:
|
if filename is None:
|
||||||
handler = StreamHandler(stream)
|
handler = StreamHandler(stream)
|
||||||
else:
|
else:
|
||||||
|
@ -244,9 +277,10 @@ def basicConfig(
|
||||||
handler.setLevel(level)
|
handler.setLevel(level)
|
||||||
handler.setFormatter(Formatter(format, datefmt))
|
handler.setFormatter(Formatter(format, datefmt))
|
||||||
|
|
||||||
logger.setLevel(level)
|
|
||||||
logger.addHandler(handler)
|
logger.addHandler(handler)
|
||||||
|
|
||||||
|
logger.setLevel(level)
|
||||||
|
|
||||||
|
|
||||||
if hasattr(sys, "atexit"):
|
if hasattr(sys, "atexit"):
|
||||||
sys.atexit(shutdown)
|
sys.atexit(shutdown)
|
||||||
|
|
Ładowanie…
Reference in New Issue