Skip to content

Commit 7b1161d

Browse files
committed
logging: Add support for custom handlers.
Any custom handlers will be passed a LogRecord instance which has members and a dict with "levelname", "message" and "name", to be used for creating a log message. The handler list is a global singleton so that sub-logging objects all use the same set of (root) handlers. The name of the root handler is also changed from None to "root", to match CPython. Signed-off-by: Damien George <[email protected]>
1 parent dedf328 commit 7b1161d

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

logging/example_logging.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,10 @@
1313
1/0
1414
except:
1515
log.exception("Some trouble (%s)", "expected")
16+
17+
class MyHandler(logging.Handler):
18+
def emit(self, record):
19+
print("levelname=%(levelname)s name=%(name)s message=%(message)s" % record.__dict__)
20+
21+
logging.getLogger().addHandler(MyHandler())
22+
logging.info("Test message7")

logging/logging.py

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,25 @@
1717

1818
_stream = sys.stderr
1919

20+
class LogRecord:
21+
def __init__(self):
22+
self.__dict__ = {}
23+
24+
def __getattr__(self, key):
25+
return self.__dict__[key]
26+
27+
class Handler:
28+
def __init__(self):
29+
pass
30+
31+
def setFormatter(self, fmtr):
32+
pass
33+
2034
class Logger:
2135

2236
level = NOTSET
37+
handlers = []
38+
record = LogRecord()
2339

2440
def __init__(self, name):
2541
self.name = name
@@ -37,12 +53,19 @@ def isEnabledFor(self, level):
3753
return level >= (self.level or _level)
3854

3955
def log(self, level, msg, *args):
40-
if level >= (self.level or _level):
41-
_stream.write("%s:%s:" % (self._level_str(level), self.name))
42-
if not args:
43-
print(msg, file=_stream)
56+
if self.isEnabledFor(level):
57+
level = self._level_str(level)
58+
if args:
59+
msg = msg % args
60+
if self.handlers:
61+
d = self.record.__dict__
62+
d["levelname"] = level
63+
d["message"] = msg
64+
d["name"] = self.name
65+
for h in self.handlers:
66+
h.emit(self.record)
4467
else:
45-
print(msg % args, file=_stream)
68+
print(level, ":", self.name, ":", msg, sep="", file=_stream)
4669

4770
def debug(self, msg, *args):
4871
self.log(DEBUG, msg, *args)
@@ -66,22 +89,24 @@ def exc(self, e, msg, *args):
6689
def exception(self, msg, *args):
6790
self.exc(sys.exc_info()[1], msg, *args)
6891

92+
def addHandler(self, hndlr):
93+
self.handlers.append(hndlr)
6994

7095
_level = INFO
7196
_loggers = {}
7297

73-
def getLogger(name):
98+
def getLogger(name="root"):
7499
if name in _loggers:
75100
return _loggers[name]
76101
l = Logger(name)
77102
_loggers[name] = l
78103
return l
79104

80105
def info(msg, *args):
81-
getLogger(None).info(msg, *args)
106+
getLogger().info(msg, *args)
82107

83108
def debug(msg, *args):
84-
getLogger(None).debug(msg, *args)
109+
getLogger().debug(msg, *args)
85110

86111
def basicConfig(level=INFO, filename=None, stream=None, format=None):
87112
global _level, _stream

0 commit comments

Comments
 (0)