Coverage for /pythoncovmergedfiles/medio/medio/usr/lib/python3.9/logging/__init__.py: 34%
908 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
1# Copyright 2001-2019 by Vinay Sajip. All Rights Reserved.
2#
3# Permission to use, copy, modify, and distribute this software and its
4# documentation for any purpose and without fee is hereby granted,
5# provided that the above copyright notice appear in all copies and that
6# both that copyright notice and this permission notice appear in
7# supporting documentation, and that the name of Vinay Sajip
8# not be used in advertising or publicity pertaining to distribution
9# of the software without specific, written prior permission.
10# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
11# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
12# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
13# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
14# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17"""
18Logging package for Python. Based on PEP 282 and comments thereto in
19comp.lang.python.
21Copyright (C) 2001-2019 Vinay Sajip. All Rights Reserved.
23To use, simply 'import logging' and log away!
24"""
26import sys, os, time, io, re, traceback, warnings, weakref, collections.abc
28from string import Template
29from string import Formatter as StrFormatter
32__all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
33 'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO',
34 'LogRecord', 'Logger', 'LoggerAdapter', 'NOTSET', 'NullHandler',
35 'StreamHandler', 'WARN', 'WARNING', 'addLevelName', 'basicConfig',
36 'captureWarnings', 'critical', 'debug', 'disable', 'error',
37 'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass',
38 'info', 'log', 'makeLogRecord', 'setLoggerClass', 'shutdown',
39 'warn', 'warning', 'getLogRecordFactory', 'setLogRecordFactory',
40 'lastResort', 'raiseExceptions']
42import threading
44__author__ = "Vinay Sajip <vinay_sajip@red-dove.com>"
45__status__ = "production"
46# The following module attributes are no longer updated.
47__version__ = "0.5.1.2"
48__date__ = "07 February 2010"
50#---------------------------------------------------------------------------
51# Miscellaneous module data
52#---------------------------------------------------------------------------
54#
55#_startTime is used as the base when calculating the relative time of events
56#
57_startTime = time.time()
59#
60#raiseExceptions is used to see if exceptions during handling should be
61#propagated
62#
63raiseExceptions = True
65#
66# If you don't want threading information in the log, set this to zero
67#
68logThreads = True
70#
71# If you don't want multiprocessing information in the log, set this to zero
72#
73logMultiprocessing = True
75#
76# If you don't want process information in the log, set this to zero
77#
78logProcesses = True
80#---------------------------------------------------------------------------
81# Level related stuff
82#---------------------------------------------------------------------------
83#
84# Default levels and level names, these can be replaced with any positive set
85# of values having corresponding names. There is a pseudo-level, NOTSET, which
86# is only really there as a lower limit for user-defined levels. Handlers and
87# loggers are initialized with NOTSET so that they will log all messages, even
88# at user-defined levels.
89#
91CRITICAL = 50
92FATAL = CRITICAL
93ERROR = 40
94WARNING = 30
95WARN = WARNING
96INFO = 20
97DEBUG = 10
98NOTSET = 0
100_levelToName = {
101 CRITICAL: 'CRITICAL',
102 ERROR: 'ERROR',
103 WARNING: 'WARNING',
104 INFO: 'INFO',
105 DEBUG: 'DEBUG',
106 NOTSET: 'NOTSET',
107}
108_nameToLevel = {
109 'CRITICAL': CRITICAL,
110 'FATAL': FATAL,
111 'ERROR': ERROR,
112 'WARN': WARNING,
113 'WARNING': WARNING,
114 'INFO': INFO,
115 'DEBUG': DEBUG,
116 'NOTSET': NOTSET,
117}
119def getLevelName(level):
120 """
121 Return the textual or numeric representation of logging level 'level'.
123 If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
124 INFO, DEBUG) then you get the corresponding string. If you have
125 associated levels with names using addLevelName then the name you have
126 associated with 'level' is returned.
128 If a numeric value corresponding to one of the defined levels is passed
129 in, the corresponding string representation is returned.
131 If a string representation of the level is passed in, the corresponding
132 numeric value is returned.
134 If no matching numeric or string value is passed in, the string
135 'Level %s' % level is returned.
136 """
137 # See Issues #22386, #27937 and #29220 for why it's this way
138 result = _levelToName.get(level)
139 if result is not None:
140 return result
141 result = _nameToLevel.get(level)
142 if result is not None:
143 return result
144 return "Level %s" % level
146def addLevelName(level, levelName):
147 """
148 Associate 'levelName' with 'level'.
150 This is used when converting levels to text during message formatting.
151 """
152 _acquireLock()
153 try: #unlikely to cause an exception, but you never know...
154 _levelToName[level] = levelName
155 _nameToLevel[levelName] = level
156 finally:
157 _releaseLock()
159if hasattr(sys, '_getframe'):
160 currentframe = lambda: sys._getframe(3)
161else: #pragma: no cover
162 def currentframe():
163 """Return the frame object for the caller's stack frame."""
164 try:
165 raise Exception
166 except Exception:
167 return sys.exc_info()[2].tb_frame.f_back
169#
170# _srcfile is used when walking the stack to check when we've got the first
171# caller stack frame, by skipping frames whose filename is that of this
172# module's source. It therefore should contain the filename of this module's
173# source file.
174#
175# Ordinarily we would use __file__ for this, but frozen modules don't always
176# have __file__ set, for some reason (see Issue #21736). Thus, we get the
177# filename from a handy code object from a function defined in this module.
178# (There's no particular reason for picking addLevelName.)
179#
181_srcfile = os.path.normcase(addLevelName.__code__.co_filename)
183# _srcfile is only used in conjunction with sys._getframe().
184# To provide compatibility with older versions of Python, set _srcfile
185# to None if _getframe() is not available; this value will prevent
186# findCaller() from being called. You can also do this if you want to avoid
187# the overhead of fetching caller information, even when _getframe() is
188# available.
189#if not hasattr(sys, '_getframe'):
190# _srcfile = None
193def _checkLevel(level):
194 if isinstance(level, int):
195 rv = level
196 elif str(level) == level:
197 if level not in _nameToLevel:
198 raise ValueError("Unknown level: %r" % level)
199 rv = _nameToLevel[level]
200 else:
201 raise TypeError("Level not an integer or a valid string: %r" % level)
202 return rv
204#---------------------------------------------------------------------------
205# Thread-related stuff
206#---------------------------------------------------------------------------
208#
209#_lock is used to serialize access to shared data structures in this module.
210#This needs to be an RLock because fileConfig() creates and configures
211#Handlers, and so might arbitrary user threads. Since Handler code updates the
212#shared dictionary _handlers, it needs to acquire the lock. But if configuring,
213#the lock would already have been acquired - so we need an RLock.
214#The same argument applies to Loggers and Manager.loggerDict.
215#
216_lock = threading.RLock()
218def _acquireLock():
219 """
220 Acquire the module-level lock for serializing access to shared data.
222 This should be released with _releaseLock().
223 """
224 if _lock:
225 _lock.acquire()
227def _releaseLock():
228 """
229 Release the module-level lock acquired by calling _acquireLock().
230 """
231 if _lock:
232 _lock.release()
235# Prevent a held logging lock from blocking a child from logging.
237if not hasattr(os, 'register_at_fork'): # Windows and friends.
238 def _register_at_fork_reinit_lock(instance):
239 pass # no-op when os.register_at_fork does not exist.
240else:
241 # A collection of instances with a _at_fork_reinit method (logging.Handler)
242 # to be called in the child after forking. The weakref avoids us keeping
243 # discarded Handler instances alive.
244 _at_fork_reinit_lock_weakset = weakref.WeakSet()
246 def _register_at_fork_reinit_lock(instance):
247 _acquireLock()
248 try:
249 _at_fork_reinit_lock_weakset.add(instance)
250 finally:
251 _releaseLock()
253 def _after_at_fork_child_reinit_locks():
254 for handler in _at_fork_reinit_lock_weakset:
255 handler._at_fork_reinit()
257 # _acquireLock() was called in the parent before forking.
258 # The lock is reinitialized to unlocked state.
259 _lock._at_fork_reinit()
261 os.register_at_fork(before=_acquireLock,
262 after_in_child=_after_at_fork_child_reinit_locks,
263 after_in_parent=_releaseLock)
266#---------------------------------------------------------------------------
267# The logging record
268#---------------------------------------------------------------------------
270class LogRecord(object):
271 """
272 A LogRecord instance represents an event being logged.
274 LogRecord instances are created every time something is logged. They
275 contain all the information pertinent to the event being logged. The
276 main information passed in is in msg and args, which are combined
277 using str(msg) % args to create the message field of the record. The
278 record also includes information such as when the record was created,
279 the source line where the logging call was made, and any exception
280 information to be logged.
281 """
282 def __init__(self, name, level, pathname, lineno,
283 msg, args, exc_info, func=None, sinfo=None, **kwargs):
284 """
285 Initialize a logging record with interesting information.
286 """
287 ct = time.time()
288 self.name = name
289 self.msg = msg
290 #
291 # The following statement allows passing of a dictionary as a sole
292 # argument, so that you can do something like
293 # logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2})
294 # Suggested by Stefan Behnel.
295 # Note that without the test for args[0], we get a problem because
296 # during formatting, we test to see if the arg is present using
297 # 'if self.args:'. If the event being logged is e.g. 'Value is %d'
298 # and if the passed arg fails 'if self.args:' then no formatting
299 # is done. For example, logger.warning('Value is %d', 0) would log
300 # 'Value is %d' instead of 'Value is 0'.
301 # For the use case of passing a dictionary, this should not be a
302 # problem.
303 # Issue #21172: a request was made to relax the isinstance check
304 # to hasattr(args[0], '__getitem__'). However, the docs on string
305 # formatting still seem to suggest a mapping object is required.
306 # Thus, while not removing the isinstance check, it does now look
307 # for collections.abc.Mapping rather than, as before, dict.
308 if (args and len(args) == 1 and isinstance(args[0], collections.abc.Mapping)
309 and args[0]):
310 args = args[0]
311 self.args = args
312 self.levelname = getLevelName(level)
313 self.levelno = level
314 self.pathname = pathname
315 try:
316 self.filename = os.path.basename(pathname)
317 self.module = os.path.splitext(self.filename)[0]
318 except (TypeError, ValueError, AttributeError):
319 self.filename = pathname
320 self.module = "Unknown module"
321 self.exc_info = exc_info
322 self.exc_text = None # used to cache the traceback text
323 self.stack_info = sinfo
324 self.lineno = lineno
325 self.funcName = func
326 self.created = ct
327 self.msecs = (ct - int(ct)) * 1000
328 self.relativeCreated = (self.created - _startTime) * 1000
329 if logThreads:
330 self.thread = threading.get_ident()
331 self.threadName = threading.current_thread().name
332 else: # pragma: no cover
333 self.thread = None
334 self.threadName = None
335 if not logMultiprocessing: # pragma: no cover
336 self.processName = None
337 else:
338 self.processName = 'MainProcess'
339 mp = sys.modules.get('multiprocessing')
340 if mp is not None:
341 # Errors may occur if multiprocessing has not finished loading
342 # yet - e.g. if a custom import hook causes third-party code
343 # to run when multiprocessing calls import. See issue 8200
344 # for an example
345 try:
346 self.processName = mp.current_process().name
347 except Exception: #pragma: no cover
348 pass
349 if logProcesses and hasattr(os, 'getpid'):
350 self.process = os.getpid()
351 else:
352 self.process = None
354 def __repr__(self):
355 return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
356 self.pathname, self.lineno, self.msg)
358 def getMessage(self):
359 """
360 Return the message for this LogRecord.
362 Return the message for this LogRecord after merging any user-supplied
363 arguments with the message.
364 """
365 msg = str(self.msg)
366 if self.args:
367 msg = msg % self.args
368 return msg
370#
371# Determine which class to use when instantiating log records.
372#
373_logRecordFactory = LogRecord
375def setLogRecordFactory(factory):
376 """
377 Set the factory to be used when instantiating a log record.
379 :param factory: A callable which will be called to instantiate
380 a log record.
381 """
382 global _logRecordFactory
383 _logRecordFactory = factory
385def getLogRecordFactory():
386 """
387 Return the factory to be used when instantiating a log record.
388 """
390 return _logRecordFactory
392def makeLogRecord(dict):
393 """
394 Make a LogRecord whose attributes are defined by the specified dictionary,
395 This function is useful for converting a logging event received over
396 a socket connection (which is sent as a dictionary) into a LogRecord
397 instance.
398 """
399 rv = _logRecordFactory(None, None, "", 0, "", (), None, None)
400 rv.__dict__.update(dict)
401 return rv
404#---------------------------------------------------------------------------
405# Formatter classes and functions
406#---------------------------------------------------------------------------
407_str_formatter = StrFormatter()
408del StrFormatter
411class PercentStyle(object):
413 default_format = '%(message)s'
414 asctime_format = '%(asctime)s'
415 asctime_search = '%(asctime)'
416 validation_pattern = re.compile(r'%\(\w+\)[#0+ -]*(\*|\d+)?(\.(\*|\d+))?[diouxefgcrsa%]', re.I)
418 def __init__(self, fmt):
419 self._fmt = fmt or self.default_format
421 def usesTime(self):
422 return self._fmt.find(self.asctime_search) >= 0
424 def validate(self):
425 """Validate the input format, ensure it matches the correct style"""
426 if not self.validation_pattern.search(self._fmt):
427 raise ValueError("Invalid format '%s' for '%s' style" % (self._fmt, self.default_format[0]))
429 def _format(self, record):
430 return self._fmt % record.__dict__
432 def format(self, record):
433 try:
434 return self._format(record)
435 except KeyError as e:
436 raise ValueError('Formatting field not found in record: %s' % e)
439class StrFormatStyle(PercentStyle):
440 default_format = '{message}'
441 asctime_format = '{asctime}'
442 asctime_search = '{asctime'
444 fmt_spec = re.compile(r'^(.?[<>=^])?[+ -]?#?0?(\d+|{\w+})?[,_]?(\.(\d+|{\w+}))?[bcdefgnosx%]?$', re.I)
445 field_spec = re.compile(r'^(\d+|\w+)(\.\w+|\[[^]]+\])*$')
447 def _format(self, record):
448 return self._fmt.format(**record.__dict__)
450 def validate(self):
451 """Validate the input format, ensure it is the correct string formatting style"""
452 fields = set()
453 try:
454 for _, fieldname, spec, conversion in _str_formatter.parse(self._fmt):
455 if fieldname:
456 if not self.field_spec.match(fieldname):
457 raise ValueError('invalid field name/expression: %r' % fieldname)
458 fields.add(fieldname)
459 if conversion and conversion not in 'rsa':
460 raise ValueError('invalid conversion: %r' % conversion)
461 if spec and not self.fmt_spec.match(spec):
462 raise ValueError('bad specifier: %r' % spec)
463 except ValueError as e:
464 raise ValueError('invalid format: %s' % e)
465 if not fields:
466 raise ValueError('invalid format: no fields')
469class StringTemplateStyle(PercentStyle):
470 default_format = '${message}'
471 asctime_format = '${asctime}'
472 asctime_search = '${asctime}'
474 def __init__(self, fmt):
475 self._fmt = fmt or self.default_format
476 self._tpl = Template(self._fmt)
478 def usesTime(self):
479 fmt = self._fmt
480 return fmt.find('$asctime') >= 0 or fmt.find(self.asctime_format) >= 0
482 def validate(self):
483 pattern = Template.pattern
484 fields = set()
485 for m in pattern.finditer(self._fmt):
486 d = m.groupdict()
487 if d['named']:
488 fields.add(d['named'])
489 elif d['braced']:
490 fields.add(d['braced'])
491 elif m.group(0) == '$':
492 raise ValueError('invalid format: bare \'$\' not allowed')
493 if not fields:
494 raise ValueError('invalid format: no fields')
496 def _format(self, record):
497 return self._tpl.substitute(**record.__dict__)
500BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
502_STYLES = {
503 '%': (PercentStyle, BASIC_FORMAT),
504 '{': (StrFormatStyle, '{levelname}:{name}:{message}'),
505 '$': (StringTemplateStyle, '${levelname}:${name}:${message}'),
506}
508class Formatter(object):
509 """
510 Formatter instances are used to convert a LogRecord to text.
512 Formatters need to know how a LogRecord is constructed. They are
513 responsible for converting a LogRecord to (usually) a string which can
514 be interpreted by either a human or an external system. The base Formatter
515 allows a formatting string to be specified. If none is supplied, the
516 style-dependent default value, "%(message)s", "{message}", or
517 "${message}", is used.
519 The Formatter can be initialized with a format string which makes use of
520 knowledge of the LogRecord attributes - e.g. the default value mentioned
521 above makes use of the fact that the user's message and arguments are pre-
522 formatted into a LogRecord's message attribute. Currently, the useful
523 attributes in a LogRecord are described by:
525 %(name)s Name of the logger (logging channel)
526 %(levelno)s Numeric logging level for the message (DEBUG, INFO,
527 WARNING, ERROR, CRITICAL)
528 %(levelname)s Text logging level for the message ("DEBUG", "INFO",
529 "WARNING", "ERROR", "CRITICAL")
530 %(pathname)s Full pathname of the source file where the logging
531 call was issued (if available)
532 %(filename)s Filename portion of pathname
533 %(module)s Module (name portion of filename)
534 %(lineno)d Source line number where the logging call was issued
535 (if available)
536 %(funcName)s Function name
537 %(created)f Time when the LogRecord was created (time.time()
538 return value)
539 %(asctime)s Textual time when the LogRecord was created
540 %(msecs)d Millisecond portion of the creation time
541 %(relativeCreated)d Time in milliseconds when the LogRecord was created,
542 relative to the time the logging module was loaded
543 (typically at application startup time)
544 %(thread)d Thread ID (if available)
545 %(threadName)s Thread name (if available)
546 %(process)d Process ID (if available)
547 %(message)s The result of record.getMessage(), computed just as
548 the record is emitted
549 """
551 converter = time.localtime
553 def __init__(self, fmt=None, datefmt=None, style='%', validate=True):
554 """
555 Initialize the formatter with specified format strings.
557 Initialize the formatter either with the specified format string, or a
558 default as described above. Allow for specialized date formatting with
559 the optional datefmt argument. If datefmt is omitted, you get an
560 ISO8601-like (or RFC 3339-like) format.
562 Use a style parameter of '%', '{' or '$' to specify that you want to
563 use one of %-formatting, :meth:`str.format` (``{}``) formatting or
564 :class:`string.Template` formatting in your format string.
566 .. versionchanged:: 3.2
567 Added the ``style`` parameter.
568 """
569 if style not in _STYLES:
570 raise ValueError('Style must be one of: %s' % ','.join(
571 _STYLES.keys()))
572 self._style = _STYLES[style][0](fmt)
573 if validate:
574 self._style.validate()
576 self._fmt = self._style._fmt
577 self.datefmt = datefmt
579 default_time_format = '%Y-%m-%d %H:%M:%S'
580 default_msec_format = '%s,%03d'
582 def formatTime(self, record, datefmt=None):
583 """
584 Return the creation time of the specified LogRecord as formatted text.
586 This method should be called from format() by a formatter which
587 wants to make use of a formatted time. This method can be overridden
588 in formatters to provide for any specific requirement, but the
589 basic behaviour is as follows: if datefmt (a string) is specified,
590 it is used with time.strftime() to format the creation time of the
591 record. Otherwise, an ISO8601-like (or RFC 3339-like) format is used.
592 The resulting string is returned. This function uses a user-configurable
593 function to convert the creation time to a tuple. By default,
594 time.localtime() is used; to change this for a particular formatter
595 instance, set the 'converter' attribute to a function with the same
596 signature as time.localtime() or time.gmtime(). To change it for all
597 formatters, for example if you want all logging times to be shown in GMT,
598 set the 'converter' attribute in the Formatter class.
599 """
600 ct = self.converter(record.created)
601 if datefmt:
602 s = time.strftime(datefmt, ct)
603 else:
604 s = time.strftime(self.default_time_format, ct)
605 if self.default_msec_format:
606 s = self.default_msec_format % (s, record.msecs)
607 return s
609 def formatException(self, ei):
610 """
611 Format and return the specified exception information as a string.
613 This default implementation just uses
614 traceback.print_exception()
615 """
616 sio = io.StringIO()
617 tb = ei[2]
618 # See issues #9427, #1553375. Commented out for now.
619 #if getattr(self, 'fullstack', False):
620 # traceback.print_stack(tb.tb_frame.f_back, file=sio)
621 traceback.print_exception(ei[0], ei[1], tb, None, sio)
622 s = sio.getvalue()
623 sio.close()
624 if s[-1:] == "\n":
625 s = s[:-1]
626 return s
628 def usesTime(self):
629 """
630 Check if the format uses the creation time of the record.
631 """
632 return self._style.usesTime()
634 def formatMessage(self, record):
635 return self._style.format(record)
637 def formatStack(self, stack_info):
638 """
639 This method is provided as an extension point for specialized
640 formatting of stack information.
642 The input data is a string as returned from a call to
643 :func:`traceback.print_stack`, but with the last trailing newline
644 removed.
646 The base implementation just returns the value passed in.
647 """
648 return stack_info
650 def format(self, record):
651 """
652 Format the specified record as text.
654 The record's attribute dictionary is used as the operand to a
655 string formatting operation which yields the returned string.
656 Before formatting the dictionary, a couple of preparatory steps
657 are carried out. The message attribute of the record is computed
658 using LogRecord.getMessage(). If the formatting string uses the
659 time (as determined by a call to usesTime(), formatTime() is
660 called to format the event time. If there is exception information,
661 it is formatted using formatException() and appended to the message.
662 """
663 record.message = record.getMessage()
664 if self.usesTime():
665 record.asctime = self.formatTime(record, self.datefmt)
666 s = self.formatMessage(record)
667 if record.exc_info:
668 # Cache the traceback text to avoid converting it multiple times
669 # (it's constant anyway)
670 if not record.exc_text:
671 record.exc_text = self.formatException(record.exc_info)
672 if record.exc_text:
673 if s[-1:] != "\n":
674 s = s + "\n"
675 s = s + record.exc_text
676 if record.stack_info:
677 if s[-1:] != "\n":
678 s = s + "\n"
679 s = s + self.formatStack(record.stack_info)
680 return s
682#
683# The default formatter to use when no other is specified
684#
685_defaultFormatter = Formatter()
687class BufferingFormatter(object):
688 """
689 A formatter suitable for formatting a number of records.
690 """
691 def __init__(self, linefmt=None):
692 """
693 Optionally specify a formatter which will be used to format each
694 individual record.
695 """
696 if linefmt:
697 self.linefmt = linefmt
698 else:
699 self.linefmt = _defaultFormatter
701 def formatHeader(self, records):
702 """
703 Return the header string for the specified records.
704 """
705 return ""
707 def formatFooter(self, records):
708 """
709 Return the footer string for the specified records.
710 """
711 return ""
713 def format(self, records):
714 """
715 Format the specified records and return the result as a string.
716 """
717 rv = ""
718 if len(records) > 0:
719 rv = rv + self.formatHeader(records)
720 for record in records:
721 rv = rv + self.linefmt.format(record)
722 rv = rv + self.formatFooter(records)
723 return rv
725#---------------------------------------------------------------------------
726# Filter classes and functions
727#---------------------------------------------------------------------------
729class Filter(object):
730 """
731 Filter instances are used to perform arbitrary filtering of LogRecords.
733 Loggers and Handlers can optionally use Filter instances to filter
734 records as desired. The base filter class only allows events which are
735 below a certain point in the logger hierarchy. For example, a filter
736 initialized with "A.B" will allow events logged by loggers "A.B",
737 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
738 initialized with the empty string, all events are passed.
739 """
740 def __init__(self, name=''):
741 """
742 Initialize a filter.
744 Initialize with the name of the logger which, together with its
745 children, will have its events allowed through the filter. If no
746 name is specified, allow every event.
747 """
748 self.name = name
749 self.nlen = len(name)
751 def filter(self, record):
752 """
753 Determine if the specified record is to be logged.
755 Returns True if the record should be logged, or False otherwise.
756 If deemed appropriate, the record may be modified in-place.
757 """
758 if self.nlen == 0:
759 return True
760 elif self.name == record.name:
761 return True
762 elif record.name.find(self.name, 0, self.nlen) != 0:
763 return False
764 return (record.name[self.nlen] == ".")
766class Filterer(object):
767 """
768 A base class for loggers and handlers which allows them to share
769 common code.
770 """
771 def __init__(self):
772 """
773 Initialize the list of filters to be an empty list.
774 """
775 self.filters = []
777 def addFilter(self, filter):
778 """
779 Add the specified filter to this handler.
780 """
781 if not (filter in self.filters):
782 self.filters.append(filter)
784 def removeFilter(self, filter):
785 """
786 Remove the specified filter from this handler.
787 """
788 if filter in self.filters:
789 self.filters.remove(filter)
791 def filter(self, record):
792 """
793 Determine if a record is loggable by consulting all the filters.
795 The default is to allow the record to be logged; any filter can veto
796 this and the record is then dropped. Returns a zero value if a record
797 is to be dropped, else non-zero.
799 .. versionchanged:: 3.2
801 Allow filters to be just callables.
802 """
803 rv = True
804 for f in self.filters:
805 if hasattr(f, 'filter'):
806 result = f.filter(record)
807 else:
808 result = f(record) # assume callable - will raise if not
809 if not result:
810 rv = False
811 break
812 return rv
814#---------------------------------------------------------------------------
815# Handler classes and functions
816#---------------------------------------------------------------------------
818_handlers = weakref.WeakValueDictionary() #map of handler names to handlers
819_handlerList = [] # added to allow handlers to be removed in reverse of order initialized
821def _removeHandlerRef(wr):
822 """
823 Remove a handler reference from the internal cleanup list.
824 """
825 # This function can be called during module teardown, when globals are
826 # set to None. It can also be called from another thread. So we need to
827 # pre-emptively grab the necessary globals and check if they're None,
828 # to prevent race conditions and failures during interpreter shutdown.
829 acquire, release, handlers = _acquireLock, _releaseLock, _handlerList
830 if acquire and release and handlers:
831 acquire()
832 try:
833 if wr in handlers:
834 handlers.remove(wr)
835 finally:
836 release()
838def _addHandlerRef(handler):
839 """
840 Add a handler to the internal cleanup list using a weak reference.
841 """
842 _acquireLock()
843 try:
844 _handlerList.append(weakref.ref(handler, _removeHandlerRef))
845 finally:
846 _releaseLock()
848class Handler(Filterer):
849 """
850 Handler instances dispatch logging events to specific destinations.
852 The base handler class. Acts as a placeholder which defines the Handler
853 interface. Handlers can optionally use Formatter instances to format
854 records as desired. By default, no formatter is specified; in this case,
855 the 'raw' message as determined by record.message is logged.
856 """
857 def __init__(self, level=NOTSET):
858 """
859 Initializes the instance - basically setting the formatter to None
860 and the filter list to empty.
861 """
862 Filterer.__init__(self)
863 self._name = None
864 self.level = _checkLevel(level)
865 self.formatter = None
866 # Add the handler to the global _handlerList (for cleanup on shutdown)
867 _addHandlerRef(self)
868 self.createLock()
870 def get_name(self):
871 return self._name
873 def set_name(self, name):
874 _acquireLock()
875 try:
876 if self._name in _handlers:
877 del _handlers[self._name]
878 self._name = name
879 if name:
880 _handlers[name] = self
881 finally:
882 _releaseLock()
884 name = property(get_name, set_name)
886 def createLock(self):
887 """
888 Acquire a thread lock for serializing access to the underlying I/O.
889 """
890 self.lock = threading.RLock()
891 _register_at_fork_reinit_lock(self)
893 def _at_fork_reinit(self):
894 self.lock._at_fork_reinit()
896 def acquire(self):
897 """
898 Acquire the I/O thread lock.
899 """
900 if self.lock:
901 self.lock.acquire()
903 def release(self):
904 """
905 Release the I/O thread lock.
906 """
907 if self.lock:
908 self.lock.release()
910 def setLevel(self, level):
911 """
912 Set the logging level of this handler. level must be an int or a str.
913 """
914 self.level = _checkLevel(level)
916 def format(self, record):
917 """
918 Format the specified record.
920 If a formatter is set, use it. Otherwise, use the default formatter
921 for the module.
922 """
923 if self.formatter:
924 fmt = self.formatter
925 else:
926 fmt = _defaultFormatter
927 return fmt.format(record)
929 def emit(self, record):
930 """
931 Do whatever it takes to actually log the specified logging record.
933 This version is intended to be implemented by subclasses and so
934 raises a NotImplementedError.
935 """
936 raise NotImplementedError('emit must be implemented '
937 'by Handler subclasses')
939 def handle(self, record):
940 """
941 Conditionally emit the specified logging record.
943 Emission depends on filters which may have been added to the handler.
944 Wrap the actual emission of the record with acquisition/release of
945 the I/O thread lock. Returns whether the filter passed the record for
946 emission.
947 """
948 rv = self.filter(record)
949 if rv:
950 self.acquire()
951 try:
952 self.emit(record)
953 finally:
954 self.release()
955 return rv
957 def setFormatter(self, fmt):
958 """
959 Set the formatter for this handler.
960 """
961 self.formatter = fmt
963 def flush(self):
964 """
965 Ensure all logging output has been flushed.
967 This version does nothing and is intended to be implemented by
968 subclasses.
969 """
970 pass
972 def close(self):
973 """
974 Tidy up any resources used by the handler.
976 This version removes the handler from an internal map of handlers,
977 _handlers, which is used for handler lookup by name. Subclasses
978 should ensure that this gets called from overridden close()
979 methods.
980 """
981 #get the module data lock, as we're updating a shared structure.
982 _acquireLock()
983 try: #unlikely to raise an exception, but you never know...
984 if self._name and self._name in _handlers:
985 del _handlers[self._name]
986 finally:
987 _releaseLock()
989 def handleError(self, record):
990 """
991 Handle errors which occur during an emit() call.
993 This method should be called from handlers when an exception is
994 encountered during an emit() call. If raiseExceptions is false,
995 exceptions get silently ignored. This is what is mostly wanted
996 for a logging system - most users will not care about errors in
997 the logging system, they are more interested in application errors.
998 You could, however, replace this with a custom handler if you wish.
999 The record which was being processed is passed in to this method.
1000 """
1001 if raiseExceptions and sys.stderr: # see issue 13807
1002 t, v, tb = sys.exc_info()
1003 try:
1004 sys.stderr.write('--- Logging error ---\n')
1005 traceback.print_exception(t, v, tb, None, sys.stderr)
1006 sys.stderr.write('Call stack:\n')
1007 # Walk the stack frame up until we're out of logging,
1008 # so as to print the calling context.
1009 frame = tb.tb_frame
1010 while (frame and os.path.dirname(frame.f_code.co_filename) ==
1011 __path__[0]):
1012 frame = frame.f_back
1013 if frame:
1014 traceback.print_stack(frame, file=sys.stderr)
1015 else:
1016 # couldn't find the right stack frame, for some reason
1017 sys.stderr.write('Logged from file %s, line %s\n' % (
1018 record.filename, record.lineno))
1019 # Issue 18671: output logging message and arguments
1020 try:
1021 sys.stderr.write('Message: %r\n'
1022 'Arguments: %s\n' % (record.msg,
1023 record.args))
1024 except RecursionError: # See issue 36272
1025 raise
1026 except Exception:
1027 sys.stderr.write('Unable to print the message and arguments'
1028 ' - possible formatting error.\nUse the'
1029 ' traceback above to help find the error.\n'
1030 )
1031 except OSError: #pragma: no cover
1032 pass # see issue 5971
1033 finally:
1034 del t, v, tb
1036 def __repr__(self):
1037 level = getLevelName(self.level)
1038 return '<%s (%s)>' % (self.__class__.__name__, level)
1040class StreamHandler(Handler):
1041 """
1042 A handler class which writes logging records, appropriately formatted,
1043 to a stream. Note that this class does not close the stream, as
1044 sys.stdout or sys.stderr may be used.
1045 """
1047 terminator = '\n'
1049 def __init__(self, stream=None):
1050 """
1051 Initialize the handler.
1053 If stream is not specified, sys.stderr is used.
1054 """
1055 Handler.__init__(self)
1056 if stream is None:
1057 stream = sys.stderr
1058 self.stream = stream
1060 def flush(self):
1061 """
1062 Flushes the stream.
1063 """
1064 self.acquire()
1065 try:
1066 if self.stream and hasattr(self.stream, "flush"):
1067 self.stream.flush()
1068 finally:
1069 self.release()
1071 def emit(self, record):
1072 """
1073 Emit a record.
1075 If a formatter is specified, it is used to format the record.
1076 The record is then written to the stream with a trailing newline. If
1077 exception information is present, it is formatted using
1078 traceback.print_exception and appended to the stream. If the stream
1079 has an 'encoding' attribute, it is used to determine how to do the
1080 output to the stream.
1081 """
1082 try:
1083 msg = self.format(record)
1084 stream = self.stream
1085 # issue 35046: merged two stream.writes into one.
1086 stream.write(msg + self.terminator)
1087 self.flush()
1088 except RecursionError: # See issue 36272
1089 raise
1090 except Exception:
1091 self.handleError(record)
1093 def setStream(self, stream):
1094 """
1095 Sets the StreamHandler's stream to the specified value,
1096 if it is different.
1098 Returns the old stream, if the stream was changed, or None
1099 if it wasn't.
1100 """
1101 if stream is self.stream:
1102 result = None
1103 else:
1104 result = self.stream
1105 self.acquire()
1106 try:
1107 self.flush()
1108 self.stream = stream
1109 finally:
1110 self.release()
1111 return result
1113 def __repr__(self):
1114 level = getLevelName(self.level)
1115 name = getattr(self.stream, 'name', '')
1116 # bpo-36015: name can be an int
1117 name = str(name)
1118 if name:
1119 name += ' '
1120 return '<%s %s(%s)>' % (self.__class__.__name__, name, level)
1123class FileHandler(StreamHandler):
1124 """
1125 A handler class which writes formatted logging records to disk files.
1126 """
1127 def __init__(self, filename, mode='a', encoding=None, delay=False, errors=None):
1128 """
1129 Open the specified file and use it as the stream for logging.
1130 """
1131 # Issue #27493: add support for Path objects to be passed in
1132 filename = os.fspath(filename)
1133 #keep the absolute path, otherwise derived classes which use this
1134 #may come a cropper when the current directory changes
1135 self.baseFilename = os.path.abspath(filename)
1136 self.mode = mode
1137 self.encoding = encoding
1138 self.errors = errors
1139 self.delay = delay
1140 if delay:
1141 #We don't open the stream, but we still need to call the
1142 #Handler constructor to set level, formatter, lock etc.
1143 Handler.__init__(self)
1144 self.stream = None
1145 else:
1146 StreamHandler.__init__(self, self._open())
1148 def close(self):
1149 """
1150 Closes the stream.
1151 """
1152 self.acquire()
1153 try:
1154 try:
1155 if self.stream:
1156 try:
1157 self.flush()
1158 finally:
1159 stream = self.stream
1160 self.stream = None
1161 if hasattr(stream, "close"):
1162 stream.close()
1163 finally:
1164 # Issue #19523: call unconditionally to
1165 # prevent a handler leak when delay is set
1166 StreamHandler.close(self)
1167 finally:
1168 self.release()
1170 def _open(self):
1171 """
1172 Open the current base file with the (original) mode and encoding.
1173 Return the resulting stream.
1174 """
1175 return open(self.baseFilename, self.mode, encoding=self.encoding,
1176 errors=self.errors)
1178 def emit(self, record):
1179 """
1180 Emit a record.
1182 If the stream was not opened because 'delay' was specified in the
1183 constructor, open it before calling the superclass's emit.
1184 """
1185 if self.stream is None:
1186 self.stream = self._open()
1187 StreamHandler.emit(self, record)
1189 def __repr__(self):
1190 level = getLevelName(self.level)
1191 return '<%s %s (%s)>' % (self.__class__.__name__, self.baseFilename, level)
1194class _StderrHandler(StreamHandler):
1195 """
1196 This class is like a StreamHandler using sys.stderr, but always uses
1197 whatever sys.stderr is currently set to rather than the value of
1198 sys.stderr at handler construction time.
1199 """
1200 def __init__(self, level=NOTSET):
1201 """
1202 Initialize the handler.
1203 """
1204 Handler.__init__(self, level)
1206 @property
1207 def stream(self):
1208 return sys.stderr
1211_defaultLastResort = _StderrHandler(WARNING)
1212lastResort = _defaultLastResort
1214#---------------------------------------------------------------------------
1215# Manager classes and functions
1216#---------------------------------------------------------------------------
1218class PlaceHolder(object):
1219 """
1220 PlaceHolder instances are used in the Manager logger hierarchy to take
1221 the place of nodes for which no loggers have been defined. This class is
1222 intended for internal use only and not as part of the public API.
1223 """
1224 def __init__(self, alogger):
1225 """
1226 Initialize with the specified logger being a child of this placeholder.
1227 """
1228 self.loggerMap = { alogger : None }
1230 def append(self, alogger):
1231 """
1232 Add the specified logger as a child of this placeholder.
1233 """
1234 if alogger not in self.loggerMap:
1235 self.loggerMap[alogger] = None
1237#
1238# Determine which class to use when instantiating loggers.
1239#
1241def setLoggerClass(klass):
1242 """
1243 Set the class to be used when instantiating a logger. The class should
1244 define __init__() such that only a name argument is required, and the
1245 __init__() should call Logger.__init__()
1246 """
1247 if klass != Logger:
1248 if not issubclass(klass, Logger):
1249 raise TypeError("logger not derived from logging.Logger: "
1250 + klass.__name__)
1251 global _loggerClass
1252 _loggerClass = klass
1254def getLoggerClass():
1255 """
1256 Return the class to be used when instantiating a logger.
1257 """
1258 return _loggerClass
1260class Manager(object):
1261 """
1262 There is [under normal circumstances] just one Manager instance, which
1263 holds the hierarchy of loggers.
1264 """
1265 def __init__(self, rootnode):
1266 """
1267 Initialize the manager with the root node of the logger hierarchy.
1268 """
1269 self.root = rootnode
1270 self.disable = 0
1271 self.emittedNoHandlerWarning = False
1272 self.loggerDict = {}
1273 self.loggerClass = None
1274 self.logRecordFactory = None
1276 @property
1277 def disable(self):
1278 return self._disable
1280 @disable.setter
1281 def disable(self, value):
1282 self._disable = _checkLevel(value)
1284 def getLogger(self, name):
1285 """
1286 Get a logger with the specified name (channel name), creating it
1287 if it doesn't yet exist. This name is a dot-separated hierarchical
1288 name, such as "a", "a.b", "a.b.c" or similar.
1290 If a PlaceHolder existed for the specified name [i.e. the logger
1291 didn't exist but a child of it did], replace it with the created
1292 logger and fix up the parent/child references which pointed to the
1293 placeholder to now point to the logger.
1294 """
1295 rv = None
1296 if not isinstance(name, str):
1297 raise TypeError('A logger name must be a string')
1298 _acquireLock()
1299 try:
1300 if name in self.loggerDict:
1301 rv = self.loggerDict[name]
1302 if isinstance(rv, PlaceHolder):
1303 ph = rv
1304 rv = (self.loggerClass or _loggerClass)(name)
1305 rv.manager = self
1306 self.loggerDict[name] = rv
1307 self._fixupChildren(ph, rv)
1308 self._fixupParents(rv)
1309 else:
1310 rv = (self.loggerClass or _loggerClass)(name)
1311 rv.manager = self
1312 self.loggerDict[name] = rv
1313 self._fixupParents(rv)
1314 finally:
1315 _releaseLock()
1316 return rv
1318 def setLoggerClass(self, klass):
1319 """
1320 Set the class to be used when instantiating a logger with this Manager.
1321 """
1322 if klass != Logger:
1323 if not issubclass(klass, Logger):
1324 raise TypeError("logger not derived from logging.Logger: "
1325 + klass.__name__)
1326 self.loggerClass = klass
1328 def setLogRecordFactory(self, factory):
1329 """
1330 Set the factory to be used when instantiating a log record with this
1331 Manager.
1332 """
1333 self.logRecordFactory = factory
1335 def _fixupParents(self, alogger):
1336 """
1337 Ensure that there are either loggers or placeholders all the way
1338 from the specified logger to the root of the logger hierarchy.
1339 """
1340 name = alogger.name
1341 i = name.rfind(".")
1342 rv = None
1343 while (i > 0) and not rv:
1344 substr = name[:i]
1345 if substr not in self.loggerDict:
1346 self.loggerDict[substr] = PlaceHolder(alogger)
1347 else:
1348 obj = self.loggerDict[substr]
1349 if isinstance(obj, Logger):
1350 rv = obj
1351 else:
1352 assert isinstance(obj, PlaceHolder)
1353 obj.append(alogger)
1354 i = name.rfind(".", 0, i - 1)
1355 if not rv:
1356 rv = self.root
1357 alogger.parent = rv
1359 def _fixupChildren(self, ph, alogger):
1360 """
1361 Ensure that children of the placeholder ph are connected to the
1362 specified logger.
1363 """
1364 name = alogger.name
1365 namelen = len(name)
1366 for c in ph.loggerMap.keys():
1367 #The if means ... if not c.parent.name.startswith(nm)
1368 if c.parent.name[:namelen] != name:
1369 alogger.parent = c.parent
1370 c.parent = alogger
1372 def _clear_cache(self):
1373 """
1374 Clear the cache for all loggers in loggerDict
1375 Called when level changes are made
1376 """
1378 _acquireLock()
1379 for logger in self.loggerDict.values():
1380 if isinstance(logger, Logger):
1381 logger._cache.clear()
1382 self.root._cache.clear()
1383 _releaseLock()
1385#---------------------------------------------------------------------------
1386# Logger classes and functions
1387#---------------------------------------------------------------------------
1389class Logger(Filterer):
1390 """
1391 Instances of the Logger class represent a single logging channel. A
1392 "logging channel" indicates an area of an application. Exactly how an
1393 "area" is defined is up to the application developer. Since an
1394 application can have any number of areas, logging channels are identified
1395 by a unique string. Application areas can be nested (e.g. an area
1396 of "input processing" might include sub-areas "read CSV files", "read
1397 XLS files" and "read Gnumeric files"). To cater for this natural nesting,
1398 channel names are organized into a namespace hierarchy where levels are
1399 separated by periods, much like the Java or Python package namespace. So
1400 in the instance given above, channel names might be "input" for the upper
1401 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
1402 There is no arbitrary limit to the depth of nesting.
1403 """
1404 def __init__(self, name, level=NOTSET):
1405 """
1406 Initialize the logger with a name and an optional level.
1407 """
1408 Filterer.__init__(self)
1409 self.name = name
1410 self.level = _checkLevel(level)
1411 self.parent = None
1412 self.propagate = True
1413 self.handlers = []
1414 self.disabled = False
1415 self._cache = {}
1417 def setLevel(self, level):
1418 """
1419 Set the logging level of this logger. level must be an int or a str.
1420 """
1421 self.level = _checkLevel(level)
1422 self.manager._clear_cache()
1424 def debug(self, msg, *args, **kwargs):
1425 """
1426 Log 'msg % args' with severity 'DEBUG'.
1428 To pass exception information, use the keyword argument exc_info with
1429 a true value, e.g.
1431 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
1432 """
1433 if self.isEnabledFor(DEBUG):
1434 self._log(DEBUG, msg, args, **kwargs)
1436 def info(self, msg, *args, **kwargs):
1437 """
1438 Log 'msg % args' with severity 'INFO'.
1440 To pass exception information, use the keyword argument exc_info with
1441 a true value, e.g.
1443 logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
1444 """
1445 if self.isEnabledFor(INFO):
1446 self._log(INFO, msg, args, **kwargs)
1448 def warning(self, msg, *args, **kwargs):
1449 """
1450 Log 'msg % args' with severity 'WARNING'.
1452 To pass exception information, use the keyword argument exc_info with
1453 a true value, e.g.
1455 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
1456 """
1457 if self.isEnabledFor(WARNING):
1458 self._log(WARNING, msg, args, **kwargs)
1460 def warn(self, msg, *args, **kwargs):
1461 warnings.warn("The 'warn' method is deprecated, "
1462 "use 'warning' instead", DeprecationWarning, 2)
1463 self.warning(msg, *args, **kwargs)
1465 def error(self, msg, *args, **kwargs):
1466 """
1467 Log 'msg % args' with severity 'ERROR'.
1469 To pass exception information, use the keyword argument exc_info with
1470 a true value, e.g.
1472 logger.error("Houston, we have a %s", "major problem", exc_info=1)
1473 """
1474 if self.isEnabledFor(ERROR):
1475 self._log(ERROR, msg, args, **kwargs)
1477 def exception(self, msg, *args, exc_info=True, **kwargs):
1478 """
1479 Convenience method for logging an ERROR with exception information.
1480 """
1481 self.error(msg, *args, exc_info=exc_info, **kwargs)
1483 def critical(self, msg, *args, **kwargs):
1484 """
1485 Log 'msg % args' with severity 'CRITICAL'.
1487 To pass exception information, use the keyword argument exc_info with
1488 a true value, e.g.
1490 logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
1491 """
1492 if self.isEnabledFor(CRITICAL):
1493 self._log(CRITICAL, msg, args, **kwargs)
1495 fatal = critical
1497 def log(self, level, msg, *args, **kwargs):
1498 """
1499 Log 'msg % args' with the integer severity 'level'.
1501 To pass exception information, use the keyword argument exc_info with
1502 a true value, e.g.
1504 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1505 """
1506 if not isinstance(level, int):
1507 if raiseExceptions:
1508 raise TypeError("level must be an integer")
1509 else:
1510 return
1511 if self.isEnabledFor(level):
1512 self._log(level, msg, args, **kwargs)
1514 def findCaller(self, stack_info=False, stacklevel=1):
1515 """
1516 Find the stack frame of the caller so that we can note the source
1517 file name, line number and function name.
1518 """
1519 f = currentframe()
1520 #On some versions of IronPython, currentframe() returns None if
1521 #IronPython isn't run with -X:Frames.
1522 if f is not None:
1523 f = f.f_back
1524 orig_f = f
1525 while f and stacklevel > 1:
1526 f = f.f_back
1527 stacklevel -= 1
1528 if not f:
1529 f = orig_f
1530 rv = "(unknown file)", 0, "(unknown function)", None
1531 while hasattr(f, "f_code"):
1532 co = f.f_code
1533 filename = os.path.normcase(co.co_filename)
1534 if filename == _srcfile:
1535 f = f.f_back
1536 continue
1537 sinfo = None
1538 if stack_info:
1539 sio = io.StringIO()
1540 sio.write('Stack (most recent call last):\n')
1541 traceback.print_stack(f, file=sio)
1542 sinfo = sio.getvalue()
1543 if sinfo[-1] == '\n':
1544 sinfo = sinfo[:-1]
1545 sio.close()
1546 rv = (co.co_filename, f.f_lineno, co.co_name, sinfo)
1547 break
1548 return rv
1550 def makeRecord(self, name, level, fn, lno, msg, args, exc_info,
1551 func=None, extra=None, sinfo=None):
1552 """
1553 A factory method which can be overridden in subclasses to create
1554 specialized LogRecords.
1555 """
1556 rv = _logRecordFactory(name, level, fn, lno, msg, args, exc_info, func,
1557 sinfo)
1558 if extra is not None:
1559 for key in extra:
1560 if (key in ["message", "asctime"]) or (key in rv.__dict__):
1561 raise KeyError("Attempt to overwrite %r in LogRecord" % key)
1562 rv.__dict__[key] = extra[key]
1563 return rv
1565 def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False,
1566 stacklevel=1):
1567 """
1568 Low-level logging routine which creates a LogRecord and then calls
1569 all the handlers of this logger to handle the record.
1570 """
1571 sinfo = None
1572 if _srcfile:
1573 #IronPython doesn't track Python frames, so findCaller raises an
1574 #exception on some versions of IronPython. We trap it here so that
1575 #IronPython can use logging.
1576 try:
1577 fn, lno, func, sinfo = self.findCaller(stack_info, stacklevel)
1578 except ValueError: # pragma: no cover
1579 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1580 else: # pragma: no cover
1581 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1582 if exc_info:
1583 if isinstance(exc_info, BaseException):
1584 exc_info = (type(exc_info), exc_info, exc_info.__traceback__)
1585 elif not isinstance(exc_info, tuple):
1586 exc_info = sys.exc_info()
1587 record = self.makeRecord(self.name, level, fn, lno, msg, args,
1588 exc_info, func, extra, sinfo)
1589 self.handle(record)
1591 def handle(self, record):
1592 """
1593 Call the handlers for the specified record.
1595 This method is used for unpickled records received from a socket, as
1596 well as those created locally. Logger-level filtering is applied.
1597 """
1598 if (not self.disabled) and self.filter(record):
1599 self.callHandlers(record)
1601 def addHandler(self, hdlr):
1602 """
1603 Add the specified handler to this logger.
1604 """
1605 _acquireLock()
1606 try:
1607 if not (hdlr in self.handlers):
1608 self.handlers.append(hdlr)
1609 finally:
1610 _releaseLock()
1612 def removeHandler(self, hdlr):
1613 """
1614 Remove the specified handler from this logger.
1615 """
1616 _acquireLock()
1617 try:
1618 if hdlr in self.handlers:
1619 self.handlers.remove(hdlr)
1620 finally:
1621 _releaseLock()
1623 def hasHandlers(self):
1624 """
1625 See if this logger has any handlers configured.
1627 Loop through all handlers for this logger and its parents in the
1628 logger hierarchy. Return True if a handler was found, else False.
1629 Stop searching up the hierarchy whenever a logger with the "propagate"
1630 attribute set to zero is found - that will be the last logger which
1631 is checked for the existence of handlers.
1632 """
1633 c = self
1634 rv = False
1635 while c:
1636 if c.handlers:
1637 rv = True
1638 break
1639 if not c.propagate:
1640 break
1641 else:
1642 c = c.parent
1643 return rv
1645 def callHandlers(self, record):
1646 """
1647 Pass a record to all relevant handlers.
1649 Loop through all handlers for this logger and its parents in the
1650 logger hierarchy. If no handler was found, output a one-off error
1651 message to sys.stderr. Stop searching up the hierarchy whenever a
1652 logger with the "propagate" attribute set to zero is found - that
1653 will be the last logger whose handlers are called.
1654 """
1655 c = self
1656 found = 0
1657 while c:
1658 for hdlr in c.handlers:
1659 found = found + 1
1660 if record.levelno >= hdlr.level:
1661 hdlr.handle(record)
1662 if not c.propagate:
1663 c = None #break out
1664 else:
1665 c = c.parent
1666 if (found == 0):
1667 if lastResort:
1668 if record.levelno >= lastResort.level:
1669 lastResort.handle(record)
1670 elif raiseExceptions and not self.manager.emittedNoHandlerWarning:
1671 sys.stderr.write("No handlers could be found for logger"
1672 " \"%s\"\n" % self.name)
1673 self.manager.emittedNoHandlerWarning = True
1675 def getEffectiveLevel(self):
1676 """
1677 Get the effective level for this logger.
1679 Loop through this logger and its parents in the logger hierarchy,
1680 looking for a non-zero logging level. Return the first one found.
1681 """
1682 logger = self
1683 while logger:
1684 if logger.level:
1685 return logger.level
1686 logger = logger.parent
1687 return NOTSET
1689 def isEnabledFor(self, level):
1690 """
1691 Is this logger enabled for level 'level'?
1692 """
1693 if self.disabled:
1694 return False
1696 try:
1697 return self._cache[level]
1698 except KeyError:
1699 _acquireLock()
1700 try:
1701 if self.manager.disable >= level:
1702 is_enabled = self._cache[level] = False
1703 else:
1704 is_enabled = self._cache[level] = (
1705 level >= self.getEffectiveLevel()
1706 )
1707 finally:
1708 _releaseLock()
1709 return is_enabled
1711 def getChild(self, suffix):
1712 """
1713 Get a logger which is a descendant to this one.
1715 This is a convenience method, such that
1717 logging.getLogger('abc').getChild('def.ghi')
1719 is the same as
1721 logging.getLogger('abc.def.ghi')
1723 It's useful, for example, when the parent logger is named using
1724 __name__ rather than a literal string.
1725 """
1726 if self.root is not self:
1727 suffix = '.'.join((self.name, suffix))
1728 return self.manager.getLogger(suffix)
1730 def __repr__(self):
1731 level = getLevelName(self.getEffectiveLevel())
1732 return '<%s %s (%s)>' % (self.__class__.__name__, self.name, level)
1734 def __reduce__(self):
1735 # In general, only the root logger will not be accessible via its name.
1736 # However, the root logger's class has its own __reduce__ method.
1737 if getLogger(self.name) is not self:
1738 import pickle
1739 raise pickle.PicklingError('logger cannot be pickled')
1740 return getLogger, (self.name,)
1743class RootLogger(Logger):
1744 """
1745 A root logger is not that different to any other logger, except that
1746 it must have a logging level and there is only one instance of it in
1747 the hierarchy.
1748 """
1749 def __init__(self, level):
1750 """
1751 Initialize the logger with the name "root".
1752 """
1753 Logger.__init__(self, "root", level)
1755 def __reduce__(self):
1756 return getLogger, ()
1758_loggerClass = Logger
1760class LoggerAdapter(object):
1761 """
1762 An adapter for loggers which makes it easier to specify contextual
1763 information in logging output.
1764 """
1766 def __init__(self, logger, extra):
1767 """
1768 Initialize the adapter with a logger and a dict-like object which
1769 provides contextual information. This constructor signature allows
1770 easy stacking of LoggerAdapters, if so desired.
1772 You can effectively pass keyword arguments as shown in the
1773 following example:
1775 adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
1776 """
1777 self.logger = logger
1778 self.extra = extra
1780 def process(self, msg, kwargs):
1781 """
1782 Process the logging message and keyword arguments passed in to
1783 a logging call to insert contextual information. You can either
1784 manipulate the message itself, the keyword args or both. Return
1785 the message and kwargs modified (or not) to suit your needs.
1787 Normally, you'll only need to override this one method in a
1788 LoggerAdapter subclass for your specific needs.
1789 """
1790 kwargs["extra"] = self.extra
1791 return msg, kwargs
1793 #
1794 # Boilerplate convenience methods
1795 #
1796 def debug(self, msg, *args, **kwargs):
1797 """
1798 Delegate a debug call to the underlying logger.
1799 """
1800 self.log(DEBUG, msg, *args, **kwargs)
1802 def info(self, msg, *args, **kwargs):
1803 """
1804 Delegate an info call to the underlying logger.
1805 """
1806 self.log(INFO, msg, *args, **kwargs)
1808 def warning(self, msg, *args, **kwargs):
1809 """
1810 Delegate a warning call to the underlying logger.
1811 """
1812 self.log(WARNING, msg, *args, **kwargs)
1814 def warn(self, msg, *args, **kwargs):
1815 warnings.warn("The 'warn' method is deprecated, "
1816 "use 'warning' instead", DeprecationWarning, 2)
1817 self.warning(msg, *args, **kwargs)
1819 def error(self, msg, *args, **kwargs):
1820 """
1821 Delegate an error call to the underlying logger.
1822 """
1823 self.log(ERROR, msg, *args, **kwargs)
1825 def exception(self, msg, *args, exc_info=True, **kwargs):
1826 """
1827 Delegate an exception call to the underlying logger.
1828 """
1829 self.log(ERROR, msg, *args, exc_info=exc_info, **kwargs)
1831 def critical(self, msg, *args, **kwargs):
1832 """
1833 Delegate a critical call to the underlying logger.
1834 """
1835 self.log(CRITICAL, msg, *args, **kwargs)
1837 def log(self, level, msg, *args, **kwargs):
1838 """
1839 Delegate a log call to the underlying logger, after adding
1840 contextual information from this adapter instance.
1841 """
1842 if self.isEnabledFor(level):
1843 msg, kwargs = self.process(msg, kwargs)
1844 self.logger.log(level, msg, *args, **kwargs)
1846 def isEnabledFor(self, level):
1847 """
1848 Is this logger enabled for level 'level'?
1849 """
1850 return self.logger.isEnabledFor(level)
1852 def setLevel(self, level):
1853 """
1854 Set the specified level on the underlying logger.
1855 """
1856 self.logger.setLevel(level)
1858 def getEffectiveLevel(self):
1859 """
1860 Get the effective level for the underlying logger.
1861 """
1862 return self.logger.getEffectiveLevel()
1864 def hasHandlers(self):
1865 """
1866 See if the underlying logger has any handlers.
1867 """
1868 return self.logger.hasHandlers()
1870 def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False):
1871 """
1872 Low-level log implementation, proxied to allow nested logger adapters.
1873 """
1874 return self.logger._log(
1875 level,
1876 msg,
1877 args,
1878 exc_info=exc_info,
1879 extra=extra,
1880 stack_info=stack_info,
1881 )
1883 @property
1884 def manager(self):
1885 return self.logger.manager
1887 @manager.setter
1888 def manager(self, value):
1889 self.logger.manager = value
1891 @property
1892 def name(self):
1893 return self.logger.name
1895 def __repr__(self):
1896 logger = self.logger
1897 level = getLevelName(logger.getEffectiveLevel())
1898 return '<%s %s (%s)>' % (self.__class__.__name__, logger.name, level)
1900root = RootLogger(WARNING)
1901Logger.root = root
1902Logger.manager = Manager(Logger.root)
1904#---------------------------------------------------------------------------
1905# Configuration classes and functions
1906#---------------------------------------------------------------------------
1908def basicConfig(**kwargs):
1909 """
1910 Do basic configuration for the logging system.
1912 This function does nothing if the root logger already has handlers
1913 configured, unless the keyword argument *force* is set to ``True``.
1914 It is a convenience method intended for use by simple scripts
1915 to do one-shot configuration of the logging package.
1917 The default behaviour is to create a StreamHandler which writes to
1918 sys.stderr, set a formatter using the BASIC_FORMAT format string, and
1919 add the handler to the root logger.
1921 A number of optional keyword arguments may be specified, which can alter
1922 the default behaviour.
1924 filename Specifies that a FileHandler be created, using the specified
1925 filename, rather than a StreamHandler.
1926 filemode Specifies the mode to open the file, if filename is specified
1927 (if filemode is unspecified, it defaults to 'a').
1928 format Use the specified format string for the handler.
1929 datefmt Use the specified date/time format.
1930 style If a format string is specified, use this to specify the
1931 type of format string (possible values '%', '{', '$', for
1932 %-formatting, :meth:`str.format` and :class:`string.Template`
1933 - defaults to '%').
1934 level Set the root logger level to the specified level.
1935 stream Use the specified stream to initialize the StreamHandler. Note
1936 that this argument is incompatible with 'filename' - if both
1937 are present, 'stream' is ignored.
1938 handlers If specified, this should be an iterable of already created
1939 handlers, which will be added to the root handler. Any handler
1940 in the list which does not have a formatter assigned will be
1941 assigned the formatter created in this function.
1942 force If this keyword is specified as true, any existing handlers
1943 attached to the root logger are removed and closed, before
1944 carrying out the configuration as specified by the other
1945 arguments.
1946 encoding If specified together with a filename, this encoding is passed to
1947 the created FileHandler, causing it to be used when the file is
1948 opened.
1949 errors If specified together with a filename, this value is passed to the
1950 created FileHandler, causing it to be used when the file is
1951 opened in text mode. If not specified, the default value is
1952 `backslashreplace`.
1954 Note that you could specify a stream created using open(filename, mode)
1955 rather than passing the filename and mode in. However, it should be
1956 remembered that StreamHandler does not close its stream (since it may be
1957 using sys.stdout or sys.stderr), whereas FileHandler closes its stream
1958 when the handler is closed.
1960 .. versionchanged:: 3.2
1961 Added the ``style`` parameter.
1963 .. versionchanged:: 3.3
1964 Added the ``handlers`` parameter. A ``ValueError`` is now thrown for
1965 incompatible arguments (e.g. ``handlers`` specified together with
1966 ``filename``/``filemode``, or ``filename``/``filemode`` specified
1967 together with ``stream``, or ``handlers`` specified together with
1968 ``stream``.
1970 .. versionchanged:: 3.8
1971 Added the ``force`` parameter.
1973 .. versionchanged:: 3.9
1974 Added the ``encoding`` and ``errors`` parameters.
1975 """
1976 # Add thread safety in case someone mistakenly calls
1977 # basicConfig() from multiple threads
1978 _acquireLock()
1979 try:
1980 force = kwargs.pop('force', False)
1981 encoding = kwargs.pop('encoding', None)
1982 errors = kwargs.pop('errors', 'backslashreplace')
1983 if force:
1984 for h in root.handlers[:]:
1985 root.removeHandler(h)
1986 h.close()
1987 if len(root.handlers) == 0:
1988 handlers = kwargs.pop("handlers", None)
1989 if handlers is None:
1990 if "stream" in kwargs and "filename" in kwargs:
1991 raise ValueError("'stream' and 'filename' should not be "
1992 "specified together")
1993 else:
1994 if "stream" in kwargs or "filename" in kwargs:
1995 raise ValueError("'stream' or 'filename' should not be "
1996 "specified together with 'handlers'")
1997 if handlers is None:
1998 filename = kwargs.pop("filename", None)
1999 mode = kwargs.pop("filemode", 'a')
2000 if filename:
2001 if 'b'in mode:
2002 errors = None
2003 h = FileHandler(filename, mode,
2004 encoding=encoding, errors=errors)
2005 else:
2006 stream = kwargs.pop("stream", None)
2007 h = StreamHandler(stream)
2008 handlers = [h]
2009 dfs = kwargs.pop("datefmt", None)
2010 style = kwargs.pop("style", '%')
2011 if style not in _STYLES:
2012 raise ValueError('Style must be one of: %s' % ','.join(
2013 _STYLES.keys()))
2014 fs = kwargs.pop("format", _STYLES[style][1])
2015 fmt = Formatter(fs, dfs, style)
2016 for h in handlers:
2017 if h.formatter is None:
2018 h.setFormatter(fmt)
2019 root.addHandler(h)
2020 level = kwargs.pop("level", None)
2021 if level is not None:
2022 root.setLevel(level)
2023 if kwargs:
2024 keys = ', '.join(kwargs.keys())
2025 raise ValueError('Unrecognised argument(s): %s' % keys)
2026 finally:
2027 _releaseLock()
2029#---------------------------------------------------------------------------
2030# Utility functions at module level.
2031# Basically delegate everything to the root logger.
2032#---------------------------------------------------------------------------
2034def getLogger(name=None):
2035 """
2036 Return a logger with the specified name, creating it if necessary.
2038 If no name is specified, return the root logger.
2039 """
2040 if not name or isinstance(name, str) and name == root.name:
2041 return root
2042 return Logger.manager.getLogger(name)
2044def critical(msg, *args, **kwargs):
2045 """
2046 Log a message with severity 'CRITICAL' on the root logger. If the logger
2047 has no handlers, call basicConfig() to add a console handler with a
2048 pre-defined format.
2049 """
2050 if len(root.handlers) == 0:
2051 basicConfig()
2052 root.critical(msg, *args, **kwargs)
2054fatal = critical
2056def error(msg, *args, **kwargs):
2057 """
2058 Log a message with severity 'ERROR' on the root logger. If the logger has
2059 no handlers, call basicConfig() to add a console handler with a pre-defined
2060 format.
2061 """
2062 if len(root.handlers) == 0:
2063 basicConfig()
2064 root.error(msg, *args, **kwargs)
2066def exception(msg, *args, exc_info=True, **kwargs):
2067 """
2068 Log a message with severity 'ERROR' on the root logger, with exception
2069 information. If the logger has no handlers, basicConfig() is called to add
2070 a console handler with a pre-defined format.
2071 """
2072 error(msg, *args, exc_info=exc_info, **kwargs)
2074def warning(msg, *args, **kwargs):
2075 """
2076 Log a message with severity 'WARNING' on the root logger. If the logger has
2077 no handlers, call basicConfig() to add a console handler with a pre-defined
2078 format.
2079 """
2080 if len(root.handlers) == 0:
2081 basicConfig()
2082 root.warning(msg, *args, **kwargs)
2084def warn(msg, *args, **kwargs):
2085 warnings.warn("The 'warn' function is deprecated, "
2086 "use 'warning' instead", DeprecationWarning, 2)
2087 warning(msg, *args, **kwargs)
2089def info(msg, *args, **kwargs):
2090 """
2091 Log a message with severity 'INFO' on the root logger. If the logger has
2092 no handlers, call basicConfig() to add a console handler with a pre-defined
2093 format.
2094 """
2095 if len(root.handlers) == 0:
2096 basicConfig()
2097 root.info(msg, *args, **kwargs)
2099def debug(msg, *args, **kwargs):
2100 """
2101 Log a message with severity 'DEBUG' on the root logger. If the logger has
2102 no handlers, call basicConfig() to add a console handler with a pre-defined
2103 format.
2104 """
2105 if len(root.handlers) == 0:
2106 basicConfig()
2107 root.debug(msg, *args, **kwargs)
2109def log(level, msg, *args, **kwargs):
2110 """
2111 Log 'msg % args' with the integer severity 'level' on the root logger. If
2112 the logger has no handlers, call basicConfig() to add a console handler
2113 with a pre-defined format.
2114 """
2115 if len(root.handlers) == 0:
2116 basicConfig()
2117 root.log(level, msg, *args, **kwargs)
2119def disable(level=CRITICAL):
2120 """
2121 Disable all logging calls of severity 'level' and below.
2122 """
2123 root.manager.disable = level
2124 root.manager._clear_cache()
2126def shutdown(handlerList=_handlerList):
2127 """
2128 Perform any cleanup actions in the logging system (e.g. flushing
2129 buffers).
2131 Should be called at application exit.
2132 """
2133 for wr in reversed(handlerList[:]):
2134 #errors might occur, for example, if files are locked
2135 #we just ignore them if raiseExceptions is not set
2136 try:
2137 h = wr()
2138 if h:
2139 try:
2140 h.acquire()
2141 h.flush()
2142 h.close()
2143 except (OSError, ValueError):
2144 # Ignore errors which might be caused
2145 # because handlers have been closed but
2146 # references to them are still around at
2147 # application exit.
2148 pass
2149 finally:
2150 h.release()
2151 except: # ignore everything, as we're shutting down
2152 if raiseExceptions:
2153 raise
2154 #else, swallow
2156#Let's try and shutdown automatically on application exit...
2157import atexit
2158atexit.register(shutdown)
2160# Null handler
2162class NullHandler(Handler):
2163 """
2164 This handler does nothing. It's intended to be used to avoid the
2165 "No handlers could be found for logger XXX" one-off warning. This is
2166 important for library code, which may contain code to log events. If a user
2167 of the library does not configure logging, the one-off warning might be
2168 produced; to avoid this, the library developer simply needs to instantiate
2169 a NullHandler and add it to the top-level logger of the library module or
2170 package.
2171 """
2172 def handle(self, record):
2173 """Stub."""
2175 def emit(self, record):
2176 """Stub."""
2178 def createLock(self):
2179 self.lock = None
2181 def _at_fork_reinit(self):
2182 pass
2184# Warnings integration
2186_warnings_showwarning = None
2188def _showwarning(message, category, filename, lineno, file=None, line=None):
2189 """
2190 Implementation of showwarnings which redirects to logging, which will first
2191 check to see if the file parameter is None. If a file is specified, it will
2192 delegate to the original warnings implementation of showwarning. Otherwise,
2193 it will call warnings.formatwarning and will log the resulting string to a
2194 warnings logger named "py.warnings" with level logging.WARNING.
2195 """
2196 if file is not None:
2197 if _warnings_showwarning is not None:
2198 _warnings_showwarning(message, category, filename, lineno, file, line)
2199 else:
2200 s = warnings.formatwarning(message, category, filename, lineno, line)
2201 logger = getLogger("py.warnings")
2202 if not logger.handlers:
2203 logger.addHandler(NullHandler())
2204 logger.warning("%s", s)
2206def captureWarnings(capture):
2207 """
2208 If capture is true, redirect all warnings to the logging package.
2209 If capture is False, ensure that warnings are not redirected to logging
2210 but to their original destinations.
2211 """
2212 global _warnings_showwarning
2213 if capture:
2214 if _warnings_showwarning is None:
2215 _warnings_showwarning = warnings.showwarning
2216 warnings.showwarning = _showwarning
2217 else:
2218 if _warnings_showwarning is not None:
2219 warnings.showwarning = _warnings_showwarning
2220 _warnings_showwarning = None