Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/logging/__init__.py: 17%
895 statements
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:13 +0000
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:13 +0000
1# Copyright 2001-2017 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-2017 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 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 Otherwise, the string "Level %s" % level is returned.
132 """
133 # See Issues #22386, #27937 and #29220 for why it's this way
134 result = _levelToName.get(level)
135 if result is not None:
136 return result
137 result = _nameToLevel.get(level)
138 if result is not None:
139 return result
140 return "Level %s" % level
142def addLevelName(level, levelName):
143 """
144 Associate 'levelName' with 'level'.
146 This is used when converting levels to text during message formatting.
147 """
148 _acquireLock()
149 try: #unlikely to cause an exception, but you never know...
150 _levelToName[level] = levelName
151 _nameToLevel[levelName] = level
152 finally:
153 _releaseLock()
155if hasattr(sys, '_getframe'):
156 currentframe = lambda: sys._getframe(3)
157else: #pragma: no cover
158 def currentframe():
159 """Return the frame object for the caller's stack frame."""
160 try:
161 raise Exception
162 except Exception:
163 return sys.exc_info()[2].tb_frame.f_back
165#
166# _srcfile is used when walking the stack to check when we've got the first
167# caller stack frame, by skipping frames whose filename is that of this
168# module's source. It therefore should contain the filename of this module's
169# source file.
170#
171# Ordinarily we would use __file__ for this, but frozen modules don't always
172# have __file__ set, for some reason (see Issue #21736). Thus, we get the
173# filename from a handy code object from a function defined in this module.
174# (There's no particular reason for picking addLevelName.)
175#
177_srcfile = os.path.normcase(addLevelName.__code__.co_filename)
179# _srcfile is only used in conjunction with sys._getframe().
180# To provide compatibility with older versions of Python, set _srcfile
181# to None if _getframe() is not available; this value will prevent
182# findCaller() from being called. You can also do this if you want to avoid
183# the overhead of fetching caller information, even when _getframe() is
184# available.
185#if not hasattr(sys, '_getframe'):
186# _srcfile = None
189def _checkLevel(level):
190 if isinstance(level, int):
191 rv = level
192 elif str(level) == level:
193 if level not in _nameToLevel:
194 raise ValueError("Unknown level: %r" % level)
195 rv = _nameToLevel[level]
196 else:
197 raise TypeError("Level not an integer or a valid string: %r" % level)
198 return rv
200#---------------------------------------------------------------------------
201# Thread-related stuff
202#---------------------------------------------------------------------------
204#
205#_lock is used to serialize access to shared data structures in this module.
206#This needs to be an RLock because fileConfig() creates and configures
207#Handlers, and so might arbitrary user threads. Since Handler code updates the
208#shared dictionary _handlers, it needs to acquire the lock. But if configuring,
209#the lock would already have been acquired - so we need an RLock.
210#The same argument applies to Loggers and Manager.loggerDict.
211#
212_lock = threading.RLock()
214def _acquireLock():
215 """
216 Acquire the module-level lock for serializing access to shared data.
218 This should be released with _releaseLock().
219 """
220 if _lock:
221 _lock.acquire()
223def _releaseLock():
224 """
225 Release the module-level lock acquired by calling _acquireLock().
226 """
227 if _lock:
228 _lock.release()
231# Prevent a held logging lock from blocking a child from logging.
233if not hasattr(os, 'register_at_fork'): # Windows and friends.
234 def _register_at_fork_reinit_lock(instance):
235 pass # no-op when os.register_at_fork does not exist.
236else:
237 # A collection of instances with a createLock method (logging.Handler)
238 # to be called in the child after forking. The weakref avoids us keeping
239 # discarded Handler instances alive. A set is used to avoid accumulating
240 # duplicate registrations as createLock() is responsible for registering
241 # a new Handler instance with this set in the first place.
242 _at_fork_reinit_lock_weakset = weakref.WeakSet()
244 def _register_at_fork_reinit_lock(instance):
245 _acquireLock()
246 try:
247 _at_fork_reinit_lock_weakset.add(instance)
248 finally:
249 _releaseLock()
251 def _after_at_fork_child_reinit_locks():
252 # _acquireLock() was called in the parent before forking.
253 for handler in _at_fork_reinit_lock_weakset:
254 try:
255 handler.createLock()
256 except Exception as err:
257 # Similar to what PyErr_WriteUnraisable does.
258 print("Ignoring exception from logging atfork", instance,
259 "._reinit_lock() method:", err, file=sys.stderr)
260 _releaseLock() # Acquired by os.register_at_fork(before=.
263 os.register_at_fork(before=_acquireLock,
264 after_in_child=_after_at_fork_child_reinit_locks,
265 after_in_parent=_releaseLock)
268#---------------------------------------------------------------------------
269# The logging record
270#---------------------------------------------------------------------------
272class LogRecord(object):
273 """
274 A LogRecord instance represents an event being logged.
276 LogRecord instances are created every time something is logged. They
277 contain all the information pertinent to the event being logged. The
278 main information passed in is in msg and args, which are combined
279 using str(msg) % args to create the message field of the record. The
280 record also includes information such as when the record was created,
281 the source line where the logging call was made, and any exception
282 information to be logged.
283 """
284 def __init__(self, name, level, pathname, lineno,
285 msg, args, exc_info, func=None, sinfo=None, **kwargs):
286 """
287 Initialize a logging record with interesting information.
288 """
289 ct = time.time()
290 self.name = name
291 self.msg = msg
292 #
293 # The following statement allows passing of a dictionary as a sole
294 # argument, so that you can do something like
295 # logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2})
296 # Suggested by Stefan Behnel.
297 # Note that without the test for args[0], we get a problem because
298 # during formatting, we test to see if the arg is present using
299 # 'if self.args:'. If the event being logged is e.g. 'Value is %d'
300 # and if the passed arg fails 'if self.args:' then no formatting
301 # is done. For example, logger.warning('Value is %d', 0) would log
302 # 'Value is %d' instead of 'Value is 0'.
303 # For the use case of passing a dictionary, this should not be a
304 # problem.
305 # Issue #21172: a request was made to relax the isinstance check
306 # to hasattr(args[0], '__getitem__'). However, the docs on string
307 # formatting still seem to suggest a mapping object is required.
308 # Thus, while not removing the isinstance check, it does now look
309 # for collections.abc.Mapping rather than, as before, dict.
310 if (args and len(args) == 1 and isinstance(args[0], collections.abc.Mapping)
311 and args[0]):
312 args = args[0]
313 self.args = args
314 self.levelname = getLevelName(level)
315 self.levelno = level
316 self.pathname = pathname
317 try:
318 self.filename = os.path.basename(pathname)
319 self.module = os.path.splitext(self.filename)[0]
320 except (TypeError, ValueError, AttributeError):
321 self.filename = pathname
322 self.module = "Unknown module"
323 self.exc_info = exc_info
324 self.exc_text = None # used to cache the traceback text
325 self.stack_info = sinfo
326 self.lineno = lineno
327 self.funcName = func
328 self.created = ct
329 self.msecs = (ct - int(ct)) * 1000
330 self.relativeCreated = (self.created - _startTime) * 1000
331 if logThreads:
332 self.thread = threading.get_ident()
333 self.threadName = threading.current_thread().name
334 else: # pragma: no cover
335 self.thread = None
336 self.threadName = None
337 if not logMultiprocessing: # pragma: no cover
338 self.processName = None
339 else:
340 self.processName = 'MainProcess'
341 mp = sys.modules.get('multiprocessing')
342 if mp is not None:
343 # Errors may occur if multiprocessing has not finished loading
344 # yet - e.g. if a custom import hook causes third-party code
345 # to run when multiprocessing calls import. See issue 8200
346 # for an example
347 try:
348 self.processName = mp.current_process().name
349 except Exception: #pragma: no cover
350 pass
351 if logProcesses and hasattr(os, 'getpid'):
352 self.process = os.getpid()
353 else:
354 self.process = None
356 def __repr__(self):
357 return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
358 self.pathname, self.lineno, self.msg)
360 def getMessage(self):
361 """
362 Return the message for this LogRecord.
364 Return the message for this LogRecord after merging any user-supplied
365 arguments with the message.
366 """
367 msg = str(self.msg)
368 if self.args:
369 msg = msg % self.args
370 return msg
372#
373# Determine which class to use when instantiating log records.
374#
375_logRecordFactory = LogRecord
377def setLogRecordFactory(factory):
378 """
379 Set the factory to be used when instantiating a log record.
381 :param factory: A callable which will be called to instantiate
382 a log record.
383 """
384 global _logRecordFactory
385 _logRecordFactory = factory
387def getLogRecordFactory():
388 """
389 Return the factory to be used when instantiating a log record.
390 """
392 return _logRecordFactory
394def makeLogRecord(dict):
395 """
396 Make a LogRecord whose attributes are defined by the specified dictionary,
397 This function is useful for converting a logging event received over
398 a socket connection (which is sent as a dictionary) into a LogRecord
399 instance.
400 """
401 rv = _logRecordFactory(None, None, "", 0, "", (), None, None)
402 rv.__dict__.update(dict)
403 return rv
406#---------------------------------------------------------------------------
407# Formatter classes and functions
408#---------------------------------------------------------------------------
409_str_formatter = StrFormatter()
410del StrFormatter
413class PercentStyle(object):
415 default_format = '%(message)s'
416 asctime_format = '%(asctime)s'
417 asctime_search = '%(asctime)'
418 validation_pattern = re.compile(r'%\(\w+\)[#0+ -]*(\*|\d+)?(\.(\*|\d+))?[diouxefgcrsa%]', re.I)
420 def __init__(self, fmt):
421 self._fmt = fmt or self.default_format
423 def usesTime(self):
424 return self._fmt.find(self.asctime_search) >= 0
426 def validate(self):
427 """Validate the input format, ensure it matches the correct style"""
428 if not self.validation_pattern.search(self._fmt):
429 raise ValueError("Invalid format '%s' for '%s' style" % (self._fmt, self.default_format[0]))
431 def _format(self, record):
432 return self._fmt % record.__dict__
434 def format(self, record):
435 try:
436 return self._format(record)
437 except KeyError as e:
438 raise ValueError('Formatting field not found in record: %s' % e)
441class StrFormatStyle(PercentStyle):
442 default_format = '{message}'
443 asctime_format = '{asctime}'
444 asctime_search = '{asctime'
446 fmt_spec = re.compile(r'^(.?[<>=^])?[+ -]?#?0?(\d+|{\w+})?[,_]?(\.(\d+|{\w+}))?[bcdefgnosx%]?$', re.I)
447 field_spec = re.compile(r'^(\d+|\w+)(\.\w+|\[[^]]+\])*$')
449 def _format(self, record):
450 return self._fmt.format(**record.__dict__)
452 def validate(self):
453 """Validate the input format, ensure it is the correct string formatting style"""
454 fields = set()
455 try:
456 for _, fieldname, spec, conversion in _str_formatter.parse(self._fmt):
457 if fieldname:
458 if not self.field_spec.match(fieldname):
459 raise ValueError('invalid field name/expression: %r' % fieldname)
460 fields.add(fieldname)
461 if conversion and conversion not in 'rsa':
462 raise ValueError('invalid conversion: %r' % conversion)
463 if spec and not self.fmt_spec.match(spec):
464 raise ValueError('bad specifier: %r' % spec)
465 except ValueError as e:
466 raise ValueError('invalid format: %s' % e)
467 if not fields:
468 raise ValueError('invalid format: no fields')
471class StringTemplateStyle(PercentStyle):
472 default_format = '${message}'
473 asctime_format = '${asctime}'
474 asctime_search = '${asctime}'
476 def __init__(self, fmt):
477 self._fmt = fmt or self.default_format
478 self._tpl = Template(self._fmt)
480 def usesTime(self):
481 fmt = self._fmt
482 return fmt.find('$asctime') >= 0 or fmt.find(self.asctime_format) >= 0
484 def validate(self):
485 pattern = Template.pattern
486 fields = set()
487 for m in pattern.finditer(self._fmt):
488 d = m.groupdict()
489 if d['named']:
490 fields.add(d['named'])
491 elif d['braced']:
492 fields.add(d['braced'])
493 elif m.group(0) == '$':
494 raise ValueError('invalid format: bare \'$\' not allowed')
495 if not fields:
496 raise ValueError('invalid format: no fields')
498 def _format(self, record):
499 return self._tpl.substitute(**record.__dict__)
502BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
504_STYLES = {
505 '%': (PercentStyle, BASIC_FORMAT),
506 '{': (StrFormatStyle, '{levelname}:{name}:{message}'),
507 '$': (StringTemplateStyle, '${levelname}:${name}:${message}'),
508}
510class Formatter(object):
511 """
512 Formatter instances are used to convert a LogRecord to text.
514 Formatters need to know how a LogRecord is constructed. They are
515 responsible for converting a LogRecord to (usually) a string which can
516 be interpreted by either a human or an external system. The base Formatter
517 allows a formatting string to be specified. If none is supplied, the
518 the style-dependent default value, "%(message)s", "{message}", or
519 "${message}", is used.
521 The Formatter can be initialized with a format string which makes use of
522 knowledge of the LogRecord attributes - e.g. the default value mentioned
523 above makes use of the fact that the user's message and arguments are pre-
524 formatted into a LogRecord's message attribute. Currently, the useful
525 attributes in a LogRecord are described by:
527 %(name)s Name of the logger (logging channel)
528 %(levelno)s Numeric logging level for the message (DEBUG, INFO,
529 WARNING, ERROR, CRITICAL)
530 %(levelname)s Text logging level for the message ("DEBUG", "INFO",
531 "WARNING", "ERROR", "CRITICAL")
532 %(pathname)s Full pathname of the source file where the logging
533 call was issued (if available)
534 %(filename)s Filename portion of pathname
535 %(module)s Module (name portion of filename)
536 %(lineno)d Source line number where the logging call was issued
537 (if available)
538 %(funcName)s Function name
539 %(created)f Time when the LogRecord was created (time.time()
540 return value)
541 %(asctime)s Textual time when the LogRecord was created
542 %(msecs)d Millisecond portion of the creation time
543 %(relativeCreated)d Time in milliseconds when the LogRecord was created,
544 relative to the time the logging module was loaded
545 (typically at application startup time)
546 %(thread)d Thread ID (if available)
547 %(threadName)s Thread name (if available)
548 %(process)d Process ID (if available)
549 %(message)s The result of record.getMessage(), computed just as
550 the record is emitted
551 """
553 converter = time.localtime
555 def __init__(self, fmt=None, datefmt=None, style='%', validate=True):
556 """
557 Initialize the formatter with specified format strings.
559 Initialize the formatter either with the specified format string, or a
560 default as described above. Allow for specialized date formatting with
561 the optional datefmt argument. If datefmt is omitted, you get an
562 ISO8601-like (or RFC 3339-like) format.
564 Use a style parameter of '%', '{' or '$' to specify that you want to
565 use one of %-formatting, :meth:`str.format` (``{}``) formatting or
566 :class:`string.Template` formatting in your format string.
568 .. versionchanged:: 3.2
569 Added the ``style`` parameter.
570 """
571 if style not in _STYLES:
572 raise ValueError('Style must be one of: %s' % ','.join(
573 _STYLES.keys()))
574 self._style = _STYLES[style][0](fmt)
575 if validate:
576 self._style.validate()
578 self._fmt = self._style._fmt
579 self.datefmt = datefmt
581 default_time_format = '%Y-%m-%d %H:%M:%S'
582 default_msec_format = '%s,%03d'
584 def formatTime(self, record, datefmt=None):
585 """
586 Return the creation time of the specified LogRecord as formatted text.
588 This method should be called from format() by a formatter which
589 wants to make use of a formatted time. This method can be overridden
590 in formatters to provide for any specific requirement, but the
591 basic behaviour is as follows: if datefmt (a string) is specified,
592 it is used with time.strftime() to format the creation time of the
593 record. Otherwise, an ISO8601-like (or RFC 3339-like) format is used.
594 The resulting string is returned. This function uses a user-configurable
595 function to convert the creation time to a tuple. By default,
596 time.localtime() is used; to change this for a particular formatter
597 instance, set the 'converter' attribute to a function with the same
598 signature as time.localtime() or time.gmtime(). To change it for all
599 formatters, for example if you want all logging times to be shown in GMT,
600 set the 'converter' attribute in the Formatter class.
601 """
602 ct = self.converter(record.created)
603 if datefmt:
604 s = time.strftime(datefmt, ct)
605 else:
606 t = time.strftime(self.default_time_format, ct)
607 s = self.default_msec_format % (t, record.msecs)
608 return s
610 def formatException(self, ei):
611 """
612 Format and return the specified exception information as a string.
614 This default implementation just uses
615 traceback.print_exception()
616 """
617 sio = io.StringIO()
618 tb = ei[2]
619 # See issues #9427, #1553375. Commented out for now.
620 #if getattr(self, 'fullstack', False):
621 # traceback.print_stack(tb.tb_frame.f_back, file=sio)
622 traceback.print_exception(ei[0], ei[1], tb, None, sio)
623 s = sio.getvalue()
624 sio.close()
625 if s[-1:] == "\n":
626 s = s[:-1]
627 return s
629 def usesTime(self):
630 """
631 Check if the format uses the creation time of the record.
632 """
633 return self._style.usesTime()
635 def formatMessage(self, record):
636 return self._style.format(record)
638 def formatStack(self, stack_info):
639 """
640 This method is provided as an extension point for specialized
641 formatting of stack information.
643 The input data is a string as returned from a call to
644 :func:`traceback.print_stack`, but with the last trailing newline
645 removed.
647 The base implementation just returns the value passed in.
648 """
649 return stack_info
651 def format(self, record):
652 """
653 Format the specified record as text.
655 The record's attribute dictionary is used as the operand to a
656 string formatting operation which yields the returned string.
657 Before formatting the dictionary, a couple of preparatory steps
658 are carried out. The message attribute of the record is computed
659 using LogRecord.getMessage(). If the formatting string uses the
660 time (as determined by a call to usesTime(), formatTime() is
661 called to format the event time. If there is exception information,
662 it is formatted using formatException() and appended to the message.
663 """
664 record.message = record.getMessage()
665 if self.usesTime():
666 record.asctime = self.formatTime(record, self.datefmt)
667 s = self.formatMessage(record)
668 if record.exc_info:
669 # Cache the traceback text to avoid converting it multiple times
670 # (it's constant anyway)
671 if not record.exc_text:
672 record.exc_text = self.formatException(record.exc_info)
673 if record.exc_text:
674 if s[-1:] != "\n":
675 s = s + "\n"
676 s = s + record.exc_text
677 if record.stack_info:
678 if s[-1:] != "\n":
679 s = s + "\n"
680 s = s + self.formatStack(record.stack_info)
681 return s
683#
684# The default formatter to use when no other is specified
685#
686_defaultFormatter = Formatter()
688class BufferingFormatter(object):
689 """
690 A formatter suitable for formatting a number of records.
691 """
692 def __init__(self, linefmt=None):
693 """
694 Optionally specify a formatter which will be used to format each
695 individual record.
696 """
697 if linefmt:
698 self.linefmt = linefmt
699 else:
700 self.linefmt = _defaultFormatter
702 def formatHeader(self, records):
703 """
704 Return the header string for the specified records.
705 """
706 return ""
708 def formatFooter(self, records):
709 """
710 Return the footer string for the specified records.
711 """
712 return ""
714 def format(self, records):
715 """
716 Format the specified records and return the result as a string.
717 """
718 rv = ""
719 if len(records) > 0:
720 rv = rv + self.formatHeader(records)
721 for record in records:
722 rv = rv + self.linefmt.format(record)
723 rv = rv + self.formatFooter(records)
724 return rv
726#---------------------------------------------------------------------------
727# Filter classes and functions
728#---------------------------------------------------------------------------
730class Filter(object):
731 """
732 Filter instances are used to perform arbitrary filtering of LogRecords.
734 Loggers and Handlers can optionally use Filter instances to filter
735 records as desired. The base filter class only allows events which are
736 below a certain point in the logger hierarchy. For example, a filter
737 initialized with "A.B" will allow events logged by loggers "A.B",
738 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
739 initialized with the empty string, all events are passed.
740 """
741 def __init__(self, name=''):
742 """
743 Initialize a filter.
745 Initialize with the name of the logger which, together with its
746 children, will have its events allowed through the filter. If no
747 name is specified, allow every event.
748 """
749 self.name = name
750 self.nlen = len(name)
752 def filter(self, record):
753 """
754 Determine if the specified record is to be logged.
756 Is the specified record to be logged? Returns 0 for no, nonzero for
757 yes. If deemed appropriate, the record may be modified in-place.
758 """
759 if self.nlen == 0:
760 return True
761 elif self.name == record.name:
762 return True
763 elif record.name.find(self.name, 0, self.nlen) != 0:
764 return False
765 return (record.name[self.nlen] == ".")
767class Filterer(object):
768 """
769 A base class for loggers and handlers which allows them to share
770 common code.
771 """
772 def __init__(self):
773 """
774 Initialize the list of filters to be an empty list.
775 """
776 self.filters = []
778 def addFilter(self, filter):
779 """
780 Add the specified filter to this handler.
781 """
782 if not (filter in self.filters):
783 self.filters.append(filter)
785 def removeFilter(self, filter):
786 """
787 Remove the specified filter from this handler.
788 """
789 if filter in self.filters:
790 self.filters.remove(filter)
792 def filter(self, record):
793 """
794 Determine if a record is loggable by consulting all the filters.
796 The default is to allow the record to be logged; any filter can veto
797 this and the record is then dropped. Returns a zero value if a record
798 is to be dropped, else non-zero.
800 .. versionchanged:: 3.2
802 Allow filters to be just callables.
803 """
804 rv = True
805 for f in self.filters:
806 if hasattr(f, 'filter'):
807 result = f.filter(record)
808 else:
809 result = f(record) # assume callable - will raise if not
810 if not result:
811 rv = False
812 break
813 return rv
815#---------------------------------------------------------------------------
816# Handler classes and functions
817#---------------------------------------------------------------------------
819_handlers = weakref.WeakValueDictionary() #map of handler names to handlers
820_handlerList = [] # added to allow handlers to be removed in reverse of order initialized
822def _removeHandlerRef(wr):
823 """
824 Remove a handler reference from the internal cleanup list.
825 """
826 # This function can be called during module teardown, when globals are
827 # set to None. It can also be called from another thread. So we need to
828 # pre-emptively grab the necessary globals and check if they're None,
829 # to prevent race conditions and failures during interpreter shutdown.
830 acquire, release, handlers = _acquireLock, _releaseLock, _handlerList
831 if acquire and release and handlers:
832 acquire()
833 try:
834 if wr in handlers:
835 handlers.remove(wr)
836 finally:
837 release()
839def _addHandlerRef(handler):
840 """
841 Add a handler to the internal cleanup list using a weak reference.
842 """
843 _acquireLock()
844 try:
845 _handlerList.append(weakref.ref(handler, _removeHandlerRef))
846 finally:
847 _releaseLock()
849class Handler(Filterer):
850 """
851 Handler instances dispatch logging events to specific destinations.
853 The base handler class. Acts as a placeholder which defines the Handler
854 interface. Handlers can optionally use Formatter instances to format
855 records as desired. By default, no formatter is specified; in this case,
856 the 'raw' message as determined by record.message is logged.
857 """
858 def __init__(self, level=NOTSET):
859 """
860 Initializes the instance - basically setting the formatter to None
861 and the filter list to empty.
862 """
863 Filterer.__init__(self)
864 self._name = None
865 self.level = _checkLevel(level)
866 self.formatter = None
867 # Add the handler to the global _handlerList (for cleanup on shutdown)
868 _addHandlerRef(self)
869 self.createLock()
871 def get_name(self):
872 return self._name
874 def set_name(self, name):
875 _acquireLock()
876 try:
877 if self._name in _handlers:
878 del _handlers[self._name]
879 self._name = name
880 if name:
881 _handlers[name] = self
882 finally:
883 _releaseLock()
885 name = property(get_name, set_name)
887 def createLock(self):
888 """
889 Acquire a thread lock for serializing access to the underlying I/O.
890 """
891 self.lock = threading.RLock()
892 _register_at_fork_reinit_lock(self)
894 def acquire(self):
895 """
896 Acquire the I/O thread lock.
897 """
898 if self.lock:
899 self.lock.acquire()
901 def release(self):
902 """
903 Release the I/O thread lock.
904 """
905 if self.lock:
906 self.lock.release()
908 def setLevel(self, level):
909 """
910 Set the logging level of this handler. level must be an int or a str.
911 """
912 self.level = _checkLevel(level)
914 def format(self, record):
915 """
916 Format the specified record.
918 If a formatter is set, use it. Otherwise, use the default formatter
919 for the module.
920 """
921 if self.formatter:
922 fmt = self.formatter
923 else:
924 fmt = _defaultFormatter
925 return fmt.format(record)
927 def emit(self, record):
928 """
929 Do whatever it takes to actually log the specified logging record.
931 This version is intended to be implemented by subclasses and so
932 raises a NotImplementedError.
933 """
934 raise NotImplementedError('emit must be implemented '
935 'by Handler subclasses')
937 def handle(self, record):
938 """
939 Conditionally emit the specified logging record.
941 Emission depends on filters which may have been added to the handler.
942 Wrap the actual emission of the record with acquisition/release of
943 the I/O thread lock. Returns whether the filter passed the record for
944 emission.
945 """
946 rv = self.filter(record)
947 if rv:
948 self.acquire()
949 try:
950 self.emit(record)
951 finally:
952 self.release()
953 return rv
955 def setFormatter(self, fmt):
956 """
957 Set the formatter for this handler.
958 """
959 self.formatter = fmt
961 def flush(self):
962 """
963 Ensure all logging output has been flushed.
965 This version does nothing and is intended to be implemented by
966 subclasses.
967 """
968 pass
970 def close(self):
971 """
972 Tidy up any resources used by the handler.
974 This version removes the handler from an internal map of handlers,
975 _handlers, which is used for handler lookup by name. Subclasses
976 should ensure that this gets called from overridden close()
977 methods.
978 """
979 #get the module data lock, as we're updating a shared structure.
980 _acquireLock()
981 try: #unlikely to raise an exception, but you never know...
982 if self._name and self._name in _handlers:
983 del _handlers[self._name]
984 finally:
985 _releaseLock()
987 def handleError(self, record):
988 """
989 Handle errors which occur during an emit() call.
991 This method should be called from handlers when an exception is
992 encountered during an emit() call. If raiseExceptions is false,
993 exceptions get silently ignored. This is what is mostly wanted
994 for a logging system - most users will not care about errors in
995 the logging system, they are more interested in application errors.
996 You could, however, replace this with a custom handler if you wish.
997 The record which was being processed is passed in to this method.
998 """
999 if raiseExceptions and sys.stderr: # see issue 13807
1000 t, v, tb = sys.exc_info()
1001 try:
1002 sys.stderr.write('--- Logging error ---\n')
1003 traceback.print_exception(t, v, tb, None, sys.stderr)
1004 sys.stderr.write('Call stack:\n')
1005 # Walk the stack frame up until we're out of logging,
1006 # so as to print the calling context.
1007 frame = tb.tb_frame
1008 while (frame and os.path.dirname(frame.f_code.co_filename) ==
1009 __path__[0]):
1010 frame = frame.f_back
1011 if frame:
1012 traceback.print_stack(frame, file=sys.stderr)
1013 else:
1014 # couldn't find the right stack frame, for some reason
1015 sys.stderr.write('Logged from file %s, line %s\n' % (
1016 record.filename, record.lineno))
1017 # Issue 18671: output logging message and arguments
1018 try:
1019 sys.stderr.write('Message: %r\n'
1020 'Arguments: %s\n' % (record.msg,
1021 record.args))
1022 except RecursionError: # See issue 36272
1023 raise
1024 except Exception:
1025 sys.stderr.write('Unable to print the message and arguments'
1026 ' - possible formatting error.\nUse the'
1027 ' traceback above to help find the error.\n'
1028 )
1029 except OSError: #pragma: no cover
1030 pass # see issue 5971
1031 finally:
1032 del t, v, tb
1034 def __repr__(self):
1035 level = getLevelName(self.level)
1036 return '<%s (%s)>' % (self.__class__.__name__, level)
1038class StreamHandler(Handler):
1039 """
1040 A handler class which writes logging records, appropriately formatted,
1041 to a stream. Note that this class does not close the stream, as
1042 sys.stdout or sys.stderr may be used.
1043 """
1045 terminator = '\n'
1047 def __init__(self, stream=None):
1048 """
1049 Initialize the handler.
1051 If stream is not specified, sys.stderr is used.
1052 """
1053 Handler.__init__(self)
1054 if stream is None:
1055 stream = sys.stderr
1056 self.stream = stream
1058 def flush(self):
1059 """
1060 Flushes the stream.
1061 """
1062 self.acquire()
1063 try:
1064 if self.stream and hasattr(self.stream, "flush"):
1065 self.stream.flush()
1066 finally:
1067 self.release()
1069 def emit(self, record):
1070 """
1071 Emit a record.
1073 If a formatter is specified, it is used to format the record.
1074 The record is then written to the stream with a trailing newline. If
1075 exception information is present, it is formatted using
1076 traceback.print_exception and appended to the stream. If the stream
1077 has an 'encoding' attribute, it is used to determine how to do the
1078 output to the stream.
1079 """
1080 try:
1081 msg = self.format(record)
1082 stream = self.stream
1083 # issue 35046: merged two stream.writes into one.
1084 stream.write(msg + self.terminator)
1085 self.flush()
1086 except RecursionError: # See issue 36272
1087 raise
1088 except Exception:
1089 self.handleError(record)
1091 def setStream(self, stream):
1092 """
1093 Sets the StreamHandler's stream to the specified value,
1094 if it is different.
1096 Returns the old stream, if the stream was changed, or None
1097 if it wasn't.
1098 """
1099 if stream is self.stream:
1100 result = None
1101 else:
1102 result = self.stream
1103 self.acquire()
1104 try:
1105 self.flush()
1106 self.stream = stream
1107 finally:
1108 self.release()
1109 return result
1111 def __repr__(self):
1112 level = getLevelName(self.level)
1113 name = getattr(self.stream, 'name', '')
1114 # bpo-36015: name can be an int
1115 name = str(name)
1116 if name:
1117 name += ' '
1118 return '<%s %s(%s)>' % (self.__class__.__name__, name, level)
1121class FileHandler(StreamHandler):
1122 """
1123 A handler class which writes formatted logging records to disk files.
1124 """
1125 def __init__(self, filename, mode='a', encoding=None, delay=False):
1126 """
1127 Open the specified file and use it as the stream for logging.
1128 """
1129 # Issue #27493: add support for Path objects to be passed in
1130 filename = os.fspath(filename)
1131 #keep the absolute path, otherwise derived classes which use this
1132 #may come a cropper when the current directory changes
1133 self.baseFilename = os.path.abspath(filename)
1134 self.mode = mode
1135 self.encoding = encoding
1136 self.delay = delay
1137 if delay:
1138 #We don't open the stream, but we still need to call the
1139 #Handler constructor to set level, formatter, lock etc.
1140 Handler.__init__(self)
1141 self.stream = None
1142 else:
1143 StreamHandler.__init__(self, self._open())
1145 def close(self):
1146 """
1147 Closes the stream.
1148 """
1149 self.acquire()
1150 try:
1151 try:
1152 if self.stream:
1153 try:
1154 self.flush()
1155 finally:
1156 stream = self.stream
1157 self.stream = None
1158 if hasattr(stream, "close"):
1159 stream.close()
1160 finally:
1161 # Issue #19523: call unconditionally to
1162 # prevent a handler leak when delay is set
1163 StreamHandler.close(self)
1164 finally:
1165 self.release()
1167 def _open(self):
1168 """
1169 Open the current base file with the (original) mode and encoding.
1170 Return the resulting stream.
1171 """
1172 return open(self.baseFilename, self.mode, encoding=self.encoding)
1174 def emit(self, record):
1175 """
1176 Emit a record.
1178 If the stream was not opened because 'delay' was specified in the
1179 constructor, open it before calling the superclass's emit.
1180 """
1181 if self.stream is None:
1182 self.stream = self._open()
1183 StreamHandler.emit(self, record)
1185 def __repr__(self):
1186 level = getLevelName(self.level)
1187 return '<%s %s (%s)>' % (self.__class__.__name__, self.baseFilename, level)
1190class _StderrHandler(StreamHandler):
1191 """
1192 This class is like a StreamHandler using sys.stderr, but always uses
1193 whatever sys.stderr is currently set to rather than the value of
1194 sys.stderr at handler construction time.
1195 """
1196 def __init__(self, level=NOTSET):
1197 """
1198 Initialize the handler.
1199 """
1200 Handler.__init__(self, level)
1202 @property
1203 def stream(self):
1204 return sys.stderr
1207_defaultLastResort = _StderrHandler(WARNING)
1208lastResort = _defaultLastResort
1210#---------------------------------------------------------------------------
1211# Manager classes and functions
1212#---------------------------------------------------------------------------
1214class PlaceHolder(object):
1215 """
1216 PlaceHolder instances are used in the Manager logger hierarchy to take
1217 the place of nodes for which no loggers have been defined. This class is
1218 intended for internal use only and not as part of the public API.
1219 """
1220 def __init__(self, alogger):
1221 """
1222 Initialize with the specified logger being a child of this placeholder.
1223 """
1224 self.loggerMap = { alogger : None }
1226 def append(self, alogger):
1227 """
1228 Add the specified logger as a child of this placeholder.
1229 """
1230 if alogger not in self.loggerMap:
1231 self.loggerMap[alogger] = None
1233#
1234# Determine which class to use when instantiating loggers.
1235#
1237def setLoggerClass(klass):
1238 """
1239 Set the class to be used when instantiating a logger. The class should
1240 define __init__() such that only a name argument is required, and the
1241 __init__() should call Logger.__init__()
1242 """
1243 if klass != Logger:
1244 if not issubclass(klass, Logger):
1245 raise TypeError("logger not derived from logging.Logger: "
1246 + klass.__name__)
1247 global _loggerClass
1248 _loggerClass = klass
1250def getLoggerClass():
1251 """
1252 Return the class to be used when instantiating a logger.
1253 """
1254 return _loggerClass
1256class Manager(object):
1257 """
1258 There is [under normal circumstances] just one Manager instance, which
1259 holds the hierarchy of loggers.
1260 """
1261 def __init__(self, rootnode):
1262 """
1263 Initialize the manager with the root node of the logger hierarchy.
1264 """
1265 self.root = rootnode
1266 self.disable = 0
1267 self.emittedNoHandlerWarning = False
1268 self.loggerDict = {}
1269 self.loggerClass = None
1270 self.logRecordFactory = None
1272 def getLogger(self, name):
1273 """
1274 Get a logger with the specified name (channel name), creating it
1275 if it doesn't yet exist. This name is a dot-separated hierarchical
1276 name, such as "a", "a.b", "a.b.c" or similar.
1278 If a PlaceHolder existed for the specified name [i.e. the logger
1279 didn't exist but a child of it did], replace it with the created
1280 logger and fix up the parent/child references which pointed to the
1281 placeholder to now point to the logger.
1282 """
1283 rv = None
1284 if not isinstance(name, str):
1285 raise TypeError('A logger name must be a string')
1286 _acquireLock()
1287 try:
1288 if name in self.loggerDict:
1289 rv = self.loggerDict[name]
1290 if isinstance(rv, PlaceHolder):
1291 ph = rv
1292 rv = (self.loggerClass or _loggerClass)(name)
1293 rv.manager = self
1294 self.loggerDict[name] = rv
1295 self._fixupChildren(ph, rv)
1296 self._fixupParents(rv)
1297 else:
1298 rv = (self.loggerClass or _loggerClass)(name)
1299 rv.manager = self
1300 self.loggerDict[name] = rv
1301 self._fixupParents(rv)
1302 finally:
1303 _releaseLock()
1304 return rv
1306 def setLoggerClass(self, klass):
1307 """
1308 Set the class to be used when instantiating a logger with this Manager.
1309 """
1310 if klass != Logger:
1311 if not issubclass(klass, Logger):
1312 raise TypeError("logger not derived from logging.Logger: "
1313 + klass.__name__)
1314 self.loggerClass = klass
1316 def setLogRecordFactory(self, factory):
1317 """
1318 Set the factory to be used when instantiating a log record with this
1319 Manager.
1320 """
1321 self.logRecordFactory = factory
1323 def _fixupParents(self, alogger):
1324 """
1325 Ensure that there are either loggers or placeholders all the way
1326 from the specified logger to the root of the logger hierarchy.
1327 """
1328 name = alogger.name
1329 i = name.rfind(".")
1330 rv = None
1331 while (i > 0) and not rv:
1332 substr = name[:i]
1333 if substr not in self.loggerDict:
1334 self.loggerDict[substr] = PlaceHolder(alogger)
1335 else:
1336 obj = self.loggerDict[substr]
1337 if isinstance(obj, Logger):
1338 rv = obj
1339 else:
1340 assert isinstance(obj, PlaceHolder)
1341 obj.append(alogger)
1342 i = name.rfind(".", 0, i - 1)
1343 if not rv:
1344 rv = self.root
1345 alogger.parent = rv
1347 def _fixupChildren(self, ph, alogger):
1348 """
1349 Ensure that children of the placeholder ph are connected to the
1350 specified logger.
1351 """
1352 name = alogger.name
1353 namelen = len(name)
1354 for c in ph.loggerMap.keys():
1355 #The if means ... if not c.parent.name.startswith(nm)
1356 if c.parent.name[:namelen] != name:
1357 alogger.parent = c.parent
1358 c.parent = alogger
1360 def _clear_cache(self):
1361 """
1362 Clear the cache for all loggers in loggerDict
1363 Called when level changes are made
1364 """
1366 _acquireLock()
1367 for logger in self.loggerDict.values():
1368 if isinstance(logger, Logger):
1369 logger._cache.clear()
1370 self.root._cache.clear()
1371 _releaseLock()
1373#---------------------------------------------------------------------------
1374# Logger classes and functions
1375#---------------------------------------------------------------------------
1377class Logger(Filterer):
1378 """
1379 Instances of the Logger class represent a single logging channel. A
1380 "logging channel" indicates an area of an application. Exactly how an
1381 "area" is defined is up to the application developer. Since an
1382 application can have any number of areas, logging channels are identified
1383 by a unique string. Application areas can be nested (e.g. an area
1384 of "input processing" might include sub-areas "read CSV files", "read
1385 XLS files" and "read Gnumeric files"). To cater for this natural nesting,
1386 channel names are organized into a namespace hierarchy where levels are
1387 separated by periods, much like the Java or Python package namespace. So
1388 in the instance given above, channel names might be "input" for the upper
1389 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
1390 There is no arbitrary limit to the depth of nesting.
1391 """
1392 def __init__(self, name, level=NOTSET):
1393 """
1394 Initialize the logger with a name and an optional level.
1395 """
1396 Filterer.__init__(self)
1397 self.name = name
1398 self.level = _checkLevel(level)
1399 self.parent = None
1400 self.propagate = True
1401 self.handlers = []
1402 self.disabled = False
1403 self._cache = {}
1405 def setLevel(self, level):
1406 """
1407 Set the logging level of this logger. level must be an int or a str.
1408 """
1409 self.level = _checkLevel(level)
1410 self.manager._clear_cache()
1412 def debug(self, msg, *args, **kwargs):
1413 """
1414 Log 'msg % args' with severity 'DEBUG'.
1416 To pass exception information, use the keyword argument exc_info with
1417 a true value, e.g.
1419 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
1420 """
1421 if self.isEnabledFor(DEBUG):
1422 self._log(DEBUG, msg, args, **kwargs)
1424 def info(self, msg, *args, **kwargs):
1425 """
1426 Log 'msg % args' with severity 'INFO'.
1428 To pass exception information, use the keyword argument exc_info with
1429 a true value, e.g.
1431 logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
1432 """
1433 if self.isEnabledFor(INFO):
1434 self._log(INFO, msg, args, **kwargs)
1436 def warning(self, msg, *args, **kwargs):
1437 """
1438 Log 'msg % args' with severity 'WARNING'.
1440 To pass exception information, use the keyword argument exc_info with
1441 a true value, e.g.
1443 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
1444 """
1445 if self.isEnabledFor(WARNING):
1446 self._log(WARNING, msg, args, **kwargs)
1448 def warn(self, msg, *args, **kwargs):
1449 warnings.warn("The 'warn' method is deprecated, "
1450 "use 'warning' instead", DeprecationWarning, 2)
1451 self.warning(msg, *args, **kwargs)
1453 def error(self, msg, *args, **kwargs):
1454 """
1455 Log 'msg % args' with severity 'ERROR'.
1457 To pass exception information, use the keyword argument exc_info with
1458 a true value, e.g.
1460 logger.error("Houston, we have a %s", "major problem", exc_info=1)
1461 """
1462 if self.isEnabledFor(ERROR):
1463 self._log(ERROR, msg, args, **kwargs)
1465 def exception(self, msg, *args, exc_info=True, **kwargs):
1466 """
1467 Convenience method for logging an ERROR with exception information.
1468 """
1469 self.error(msg, *args, exc_info=exc_info, **kwargs)
1471 def critical(self, msg, *args, **kwargs):
1472 """
1473 Log 'msg % args' with severity 'CRITICAL'.
1475 To pass exception information, use the keyword argument exc_info with
1476 a true value, e.g.
1478 logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
1479 """
1480 if self.isEnabledFor(CRITICAL):
1481 self._log(CRITICAL, msg, args, **kwargs)
1483 fatal = critical
1485 def log(self, level, msg, *args, **kwargs):
1486 """
1487 Log 'msg % args' with the integer severity 'level'.
1489 To pass exception information, use the keyword argument exc_info with
1490 a true value, e.g.
1492 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1493 """
1494 if not isinstance(level, int):
1495 if raiseExceptions:
1496 raise TypeError("level must be an integer")
1497 else:
1498 return
1499 if self.isEnabledFor(level):
1500 self._log(level, msg, args, **kwargs)
1502 def findCaller(self, stack_info=False, stacklevel=1):
1503 """
1504 Find the stack frame of the caller so that we can note the source
1505 file name, line number and function name.
1506 """
1507 f = currentframe()
1508 #On some versions of IronPython, currentframe() returns None if
1509 #IronPython isn't run with -X:Frames.
1510 if f is not None:
1511 f = f.f_back
1512 orig_f = f
1513 while f and stacklevel > 1:
1514 f = f.f_back
1515 stacklevel -= 1
1516 if not f:
1517 f = orig_f
1518 rv = "(unknown file)", 0, "(unknown function)", None
1519 while hasattr(f, "f_code"):
1520 co = f.f_code
1521 filename = os.path.normcase(co.co_filename)
1522 if filename == _srcfile:
1523 f = f.f_back
1524 continue
1525 sinfo = None
1526 if stack_info:
1527 sio = io.StringIO()
1528 sio.write('Stack (most recent call last):\n')
1529 traceback.print_stack(f, file=sio)
1530 sinfo = sio.getvalue()
1531 if sinfo[-1] == '\n':
1532 sinfo = sinfo[:-1]
1533 sio.close()
1534 rv = (co.co_filename, f.f_lineno, co.co_name, sinfo)
1535 break
1536 return rv
1538 def makeRecord(self, name, level, fn, lno, msg, args, exc_info,
1539 func=None, extra=None, sinfo=None):
1540 """
1541 A factory method which can be overridden in subclasses to create
1542 specialized LogRecords.
1543 """
1544 rv = _logRecordFactory(name, level, fn, lno, msg, args, exc_info, func,
1545 sinfo)
1546 if extra is not None:
1547 for key in extra:
1548 if (key in ["message", "asctime"]) or (key in rv.__dict__):
1549 raise KeyError("Attempt to overwrite %r in LogRecord" % key)
1550 rv.__dict__[key] = extra[key]
1551 return rv
1553 def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False,
1554 stacklevel=1):
1555 """
1556 Low-level logging routine which creates a LogRecord and then calls
1557 all the handlers of this logger to handle the record.
1558 """
1559 sinfo = None
1560 if _srcfile:
1561 #IronPython doesn't track Python frames, so findCaller raises an
1562 #exception on some versions of IronPython. We trap it here so that
1563 #IronPython can use logging.
1564 try:
1565 fn, lno, func, sinfo = self.findCaller(stack_info, stacklevel)
1566 except ValueError: # pragma: no cover
1567 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1568 else: # pragma: no cover
1569 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1570 if exc_info:
1571 if isinstance(exc_info, BaseException):
1572 exc_info = (type(exc_info), exc_info, exc_info.__traceback__)
1573 elif not isinstance(exc_info, tuple):
1574 exc_info = sys.exc_info()
1575 record = self.makeRecord(self.name, level, fn, lno, msg, args,
1576 exc_info, func, extra, sinfo)
1577 self.handle(record)
1579 def handle(self, record):
1580 """
1581 Call the handlers for the specified record.
1583 This method is used for unpickled records received from a socket, as
1584 well as those created locally. Logger-level filtering is applied.
1585 """
1586 if (not self.disabled) and self.filter(record):
1587 self.callHandlers(record)
1589 def addHandler(self, hdlr):
1590 """
1591 Add the specified handler to this logger.
1592 """
1593 _acquireLock()
1594 try:
1595 if not (hdlr in self.handlers):
1596 self.handlers.append(hdlr)
1597 finally:
1598 _releaseLock()
1600 def removeHandler(self, hdlr):
1601 """
1602 Remove the specified handler from this logger.
1603 """
1604 _acquireLock()
1605 try:
1606 if hdlr in self.handlers:
1607 self.handlers.remove(hdlr)
1608 finally:
1609 _releaseLock()
1611 def hasHandlers(self):
1612 """
1613 See if this logger has any handlers configured.
1615 Loop through all handlers for this logger and its parents in the
1616 logger hierarchy. Return True if a handler was found, else False.
1617 Stop searching up the hierarchy whenever a logger with the "propagate"
1618 attribute set to zero is found - that will be the last logger which
1619 is checked for the existence of handlers.
1620 """
1621 c = self
1622 rv = False
1623 while c:
1624 if c.handlers:
1625 rv = True
1626 break
1627 if not c.propagate:
1628 break
1629 else:
1630 c = c.parent
1631 return rv
1633 def callHandlers(self, record):
1634 """
1635 Pass a record to all relevant handlers.
1637 Loop through all handlers for this logger and its parents in the
1638 logger hierarchy. If no handler was found, output a one-off error
1639 message to sys.stderr. Stop searching up the hierarchy whenever a
1640 logger with the "propagate" attribute set to zero is found - that
1641 will be the last logger whose handlers are called.
1642 """
1643 c = self
1644 found = 0
1645 while c:
1646 for hdlr in c.handlers:
1647 found = found + 1
1648 if record.levelno >= hdlr.level:
1649 hdlr.handle(record)
1650 if not c.propagate:
1651 c = None #break out
1652 else:
1653 c = c.parent
1654 if (found == 0):
1655 if lastResort:
1656 if record.levelno >= lastResort.level:
1657 lastResort.handle(record)
1658 elif raiseExceptions and not self.manager.emittedNoHandlerWarning:
1659 sys.stderr.write("No handlers could be found for logger"
1660 " \"%s\"\n" % self.name)
1661 self.manager.emittedNoHandlerWarning = True
1663 def getEffectiveLevel(self):
1664 """
1665 Get the effective level for this logger.
1667 Loop through this logger and its parents in the logger hierarchy,
1668 looking for a non-zero logging level. Return the first one found.
1669 """
1670 logger = self
1671 while logger:
1672 if logger.level:
1673 return logger.level
1674 logger = logger.parent
1675 return NOTSET
1677 def isEnabledFor(self, level):
1678 """
1679 Is this logger enabled for level 'level'?
1680 """
1681 if self.disabled:
1682 return False
1684 try:
1685 return self._cache[level]
1686 except KeyError:
1687 _acquireLock()
1688 try:
1689 if self.manager.disable >= level:
1690 is_enabled = self._cache[level] = False
1691 else:
1692 is_enabled = self._cache[level] = (
1693 level >= self.getEffectiveLevel()
1694 )
1695 finally:
1696 _releaseLock()
1697 return is_enabled
1699 def getChild(self, suffix):
1700 """
1701 Get a logger which is a descendant to this one.
1703 This is a convenience method, such that
1705 logging.getLogger('abc').getChild('def.ghi')
1707 is the same as
1709 logging.getLogger('abc.def.ghi')
1711 It's useful, for example, when the parent logger is named using
1712 __name__ rather than a literal string.
1713 """
1714 if self.root is not self:
1715 suffix = '.'.join((self.name, suffix))
1716 return self.manager.getLogger(suffix)
1718 def __repr__(self):
1719 level = getLevelName(self.getEffectiveLevel())
1720 return '<%s %s (%s)>' % (self.__class__.__name__, self.name, level)
1722 def __reduce__(self):
1723 # In general, only the root logger will not be accessible via its name.
1724 # However, the root logger's class has its own __reduce__ method.
1725 if getLogger(self.name) is not self:
1726 import pickle
1727 raise pickle.PicklingError('logger cannot be pickled')
1728 return getLogger, (self.name,)
1731class RootLogger(Logger):
1732 """
1733 A root logger is not that different to any other logger, except that
1734 it must have a logging level and there is only one instance of it in
1735 the hierarchy.
1736 """
1737 def __init__(self, level):
1738 """
1739 Initialize the logger with the name "root".
1740 """
1741 Logger.__init__(self, "root", level)
1743 def __reduce__(self):
1744 return getLogger, ()
1746_loggerClass = Logger
1748class LoggerAdapter(object):
1749 """
1750 An adapter for loggers which makes it easier to specify contextual
1751 information in logging output.
1752 """
1754 def __init__(self, logger, extra):
1755 """
1756 Initialize the adapter with a logger and a dict-like object which
1757 provides contextual information. This constructor signature allows
1758 easy stacking of LoggerAdapters, if so desired.
1760 You can effectively pass keyword arguments as shown in the
1761 following example:
1763 adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
1764 """
1765 self.logger = logger
1766 self.extra = extra
1768 def process(self, msg, kwargs):
1769 """
1770 Process the logging message and keyword arguments passed in to
1771 a logging call to insert contextual information. You can either
1772 manipulate the message itself, the keyword args or both. Return
1773 the message and kwargs modified (or not) to suit your needs.
1775 Normally, you'll only need to override this one method in a
1776 LoggerAdapter subclass for your specific needs.
1777 """
1778 kwargs["extra"] = self.extra
1779 return msg, kwargs
1781 #
1782 # Boilerplate convenience methods
1783 #
1784 def debug(self, msg, *args, **kwargs):
1785 """
1786 Delegate a debug call to the underlying logger.
1787 """
1788 self.log(DEBUG, msg, *args, **kwargs)
1790 def info(self, msg, *args, **kwargs):
1791 """
1792 Delegate an info call to the underlying logger.
1793 """
1794 self.log(INFO, msg, *args, **kwargs)
1796 def warning(self, msg, *args, **kwargs):
1797 """
1798 Delegate a warning call to the underlying logger.
1799 """
1800 self.log(WARNING, msg, *args, **kwargs)
1802 def warn(self, msg, *args, **kwargs):
1803 warnings.warn("The 'warn' method is deprecated, "
1804 "use 'warning' instead", DeprecationWarning, 2)
1805 self.warning(msg, *args, **kwargs)
1807 def error(self, msg, *args, **kwargs):
1808 """
1809 Delegate an error call to the underlying logger.
1810 """
1811 self.log(ERROR, msg, *args, **kwargs)
1813 def exception(self, msg, *args, exc_info=True, **kwargs):
1814 """
1815 Delegate an exception call to the underlying logger.
1816 """
1817 self.log(ERROR, msg, *args, exc_info=exc_info, **kwargs)
1819 def critical(self, msg, *args, **kwargs):
1820 """
1821 Delegate a critical call to the underlying logger.
1822 """
1823 self.log(CRITICAL, msg, *args, **kwargs)
1825 def log(self, level, msg, *args, **kwargs):
1826 """
1827 Delegate a log call to the underlying logger, after adding
1828 contextual information from this adapter instance.
1829 """
1830 if self.isEnabledFor(level):
1831 msg, kwargs = self.process(msg, kwargs)
1832 self.logger.log(level, msg, *args, **kwargs)
1834 def isEnabledFor(self, level):
1835 """
1836 Is this logger enabled for level 'level'?
1837 """
1838 return self.logger.isEnabledFor(level)
1840 def setLevel(self, level):
1841 """
1842 Set the specified level on the underlying logger.
1843 """
1844 self.logger.setLevel(level)
1846 def getEffectiveLevel(self):
1847 """
1848 Get the effective level for the underlying logger.
1849 """
1850 return self.logger.getEffectiveLevel()
1852 def hasHandlers(self):
1853 """
1854 See if the underlying logger has any handlers.
1855 """
1856 return self.logger.hasHandlers()
1858 def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False):
1859 """
1860 Low-level log implementation, proxied to allow nested logger adapters.
1861 """
1862 return self.logger._log(
1863 level,
1864 msg,
1865 args,
1866 exc_info=exc_info,
1867 extra=extra,
1868 stack_info=stack_info,
1869 )
1871 @property
1872 def manager(self):
1873 return self.logger.manager
1875 @manager.setter
1876 def manager(self, value):
1877 self.logger.manager = value
1879 @property
1880 def name(self):
1881 return self.logger.name
1883 def __repr__(self):
1884 logger = self.logger
1885 level = getLevelName(logger.getEffectiveLevel())
1886 return '<%s %s (%s)>' % (self.__class__.__name__, logger.name, level)
1888root = RootLogger(WARNING)
1889Logger.root = root
1890Logger.manager = Manager(Logger.root)
1892#---------------------------------------------------------------------------
1893# Configuration classes and functions
1894#---------------------------------------------------------------------------
1896def basicConfig(**kwargs):
1897 """
1898 Do basic configuration for the logging system.
1900 This function does nothing if the root logger already has handlers
1901 configured, unless the keyword argument *force* is set to ``True``.
1902 It is a convenience method intended for use by simple scripts
1903 to do one-shot configuration of the logging package.
1905 The default behaviour is to create a StreamHandler which writes to
1906 sys.stderr, set a formatter using the BASIC_FORMAT format string, and
1907 add the handler to the root logger.
1909 A number of optional keyword arguments may be specified, which can alter
1910 the default behaviour.
1912 filename Specifies that a FileHandler be created, using the specified
1913 filename, rather than a StreamHandler.
1914 filemode Specifies the mode to open the file, if filename is specified
1915 (if filemode is unspecified, it defaults to 'a').
1916 format Use the specified format string for the handler.
1917 datefmt Use the specified date/time format.
1918 style If a format string is specified, use this to specify the
1919 type of format string (possible values '%', '{', '$', for
1920 %-formatting, :meth:`str.format` and :class:`string.Template`
1921 - defaults to '%').
1922 level Set the root logger level to the specified level.
1923 stream Use the specified stream to initialize the StreamHandler. Note
1924 that this argument is incompatible with 'filename' - if both
1925 are present, 'stream' is ignored.
1926 handlers If specified, this should be an iterable of already created
1927 handlers, which will be added to the root handler. Any handler
1928 in the list which does not have a formatter assigned will be
1929 assigned the formatter created in this function.
1930 force If this keyword is specified as true, any existing handlers
1931 attached to the root logger are removed and closed, before
1932 carrying out the configuration as specified by the other
1933 arguments.
1934 Note that you could specify a stream created using open(filename, mode)
1935 rather than passing the filename and mode in. However, it should be
1936 remembered that StreamHandler does not close its stream (since it may be
1937 using sys.stdout or sys.stderr), whereas FileHandler closes its stream
1938 when the handler is closed.
1940 .. versionchanged:: 3.8
1941 Added the ``force`` parameter.
1943 .. versionchanged:: 3.2
1944 Added the ``style`` parameter.
1946 .. versionchanged:: 3.3
1947 Added the ``handlers`` parameter. A ``ValueError`` is now thrown for
1948 incompatible arguments (e.g. ``handlers`` specified together with
1949 ``filename``/``filemode``, or ``filename``/``filemode`` specified
1950 together with ``stream``, or ``handlers`` specified together with
1951 ``stream``.
1952 """
1953 # Add thread safety in case someone mistakenly calls
1954 # basicConfig() from multiple threads
1955 _acquireLock()
1956 try:
1957 force = kwargs.pop('force', False)
1958 if force:
1959 for h in root.handlers[:]:
1960 root.removeHandler(h)
1961 h.close()
1962 if len(root.handlers) == 0:
1963 handlers = kwargs.pop("handlers", None)
1964 if handlers is None:
1965 if "stream" in kwargs and "filename" in kwargs:
1966 raise ValueError("'stream' and 'filename' should not be "
1967 "specified together")
1968 else:
1969 if "stream" in kwargs or "filename" in kwargs:
1970 raise ValueError("'stream' or 'filename' should not be "
1971 "specified together with 'handlers'")
1972 if handlers is None:
1973 filename = kwargs.pop("filename", None)
1974 mode = kwargs.pop("filemode", 'a')
1975 if filename:
1976 h = FileHandler(filename, mode)
1977 else:
1978 stream = kwargs.pop("stream", None)
1979 h = StreamHandler(stream)
1980 handlers = [h]
1981 dfs = kwargs.pop("datefmt", None)
1982 style = kwargs.pop("style", '%')
1983 if style not in _STYLES:
1984 raise ValueError('Style must be one of: %s' % ','.join(
1985 _STYLES.keys()))
1986 fs = kwargs.pop("format", _STYLES[style][1])
1987 fmt = Formatter(fs, dfs, style)
1988 for h in handlers:
1989 if h.formatter is None:
1990 h.setFormatter(fmt)
1991 root.addHandler(h)
1992 level = kwargs.pop("level", None)
1993 if level is not None:
1994 root.setLevel(level)
1995 if kwargs:
1996 keys = ', '.join(kwargs.keys())
1997 raise ValueError('Unrecognised argument(s): %s' % keys)
1998 finally:
1999 _releaseLock()
2001#---------------------------------------------------------------------------
2002# Utility functions at module level.
2003# Basically delegate everything to the root logger.
2004#---------------------------------------------------------------------------
2006def getLogger(name=None):
2007 """
2008 Return a logger with the specified name, creating it if necessary.
2010 If no name is specified, return the root logger.
2011 """
2012 if name:
2013 return Logger.manager.getLogger(name)
2014 else:
2015 return root
2017def critical(msg, *args, **kwargs):
2018 """
2019 Log a message with severity 'CRITICAL' on the root logger. If the logger
2020 has no handlers, call basicConfig() to add a console handler with a
2021 pre-defined format.
2022 """
2023 if len(root.handlers) == 0:
2024 basicConfig()
2025 root.critical(msg, *args, **kwargs)
2027fatal = critical
2029def error(msg, *args, **kwargs):
2030 """
2031 Log a message with severity 'ERROR' on the root logger. If the logger has
2032 no handlers, call basicConfig() to add a console handler with a pre-defined
2033 format.
2034 """
2035 if len(root.handlers) == 0:
2036 basicConfig()
2037 root.error(msg, *args, **kwargs)
2039def exception(msg, *args, exc_info=True, **kwargs):
2040 """
2041 Log a message with severity 'ERROR' on the root logger, with exception
2042 information. If the logger has no handlers, basicConfig() is called to add
2043 a console handler with a pre-defined format.
2044 """
2045 error(msg, *args, exc_info=exc_info, **kwargs)
2047def warning(msg, *args, **kwargs):
2048 """
2049 Log a message with severity 'WARNING' on the root logger. If the logger has
2050 no handlers, call basicConfig() to add a console handler with a pre-defined
2051 format.
2052 """
2053 if len(root.handlers) == 0:
2054 basicConfig()
2055 root.warning(msg, *args, **kwargs)
2057def warn(msg, *args, **kwargs):
2058 warnings.warn("The 'warn' function is deprecated, "
2059 "use 'warning' instead", DeprecationWarning, 2)
2060 warning(msg, *args, **kwargs)
2062def info(msg, *args, **kwargs):
2063 """
2064 Log a message with severity 'INFO' on the root logger. If the logger has
2065 no handlers, call basicConfig() to add a console handler with a pre-defined
2066 format.
2067 """
2068 if len(root.handlers) == 0:
2069 basicConfig()
2070 root.info(msg, *args, **kwargs)
2072def debug(msg, *args, **kwargs):
2073 """
2074 Log a message with severity 'DEBUG' on the root logger. If the logger has
2075 no handlers, call basicConfig() to add a console handler with a pre-defined
2076 format.
2077 """
2078 if len(root.handlers) == 0:
2079 basicConfig()
2080 root.debug(msg, *args, **kwargs)
2082def log(level, msg, *args, **kwargs):
2083 """
2084 Log 'msg % args' with the integer severity 'level' on the root logger. If
2085 the logger has no handlers, call basicConfig() to add a console handler
2086 with a pre-defined format.
2087 """
2088 if len(root.handlers) == 0:
2089 basicConfig()
2090 root.log(level, msg, *args, **kwargs)
2092def disable(level=CRITICAL):
2093 """
2094 Disable all logging calls of severity 'level' and below.
2095 """
2096 root.manager.disable = level
2097 root.manager._clear_cache()
2099def shutdown(handlerList=_handlerList):
2100 """
2101 Perform any cleanup actions in the logging system (e.g. flushing
2102 buffers).
2104 Should be called at application exit.
2105 """
2106 for wr in reversed(handlerList[:]):
2107 #errors might occur, for example, if files are locked
2108 #we just ignore them if raiseExceptions is not set
2109 try:
2110 h = wr()
2111 if h:
2112 try:
2113 h.acquire()
2114 h.flush()
2115 h.close()
2116 except (OSError, ValueError):
2117 # Ignore errors which might be caused
2118 # because handlers have been closed but
2119 # references to them are still around at
2120 # application exit.
2121 pass
2122 finally:
2123 h.release()
2124 except: # ignore everything, as we're shutting down
2125 if raiseExceptions:
2126 raise
2127 #else, swallow
2129#Let's try and shutdown automatically on application exit...
2130import atexit
2131atexit.register(shutdown)
2133# Null handler
2135class NullHandler(Handler):
2136 """
2137 This handler does nothing. It's intended to be used to avoid the
2138 "No handlers could be found for logger XXX" one-off warning. This is
2139 important for library code, which may contain code to log events. If a user
2140 of the library does not configure logging, the one-off warning might be
2141 produced; to avoid this, the library developer simply needs to instantiate
2142 a NullHandler and add it to the top-level logger of the library module or
2143 package.
2144 """
2145 def handle(self, record):
2146 """Stub."""
2148 def emit(self, record):
2149 """Stub."""
2151 def createLock(self):
2152 self.lock = None
2154# Warnings integration
2156_warnings_showwarning = None
2158def _showwarning(message, category, filename, lineno, file=None, line=None):
2159 """
2160 Implementation of showwarnings which redirects to logging, which will first
2161 check to see if the file parameter is None. If a file is specified, it will
2162 delegate to the original warnings implementation of showwarning. Otherwise,
2163 it will call warnings.formatwarning and will log the resulting string to a
2164 warnings logger named "py.warnings" with level logging.WARNING.
2165 """
2166 if file is not None:
2167 if _warnings_showwarning is not None:
2168 _warnings_showwarning(message, category, filename, lineno, file, line)
2169 else:
2170 s = warnings.formatwarning(message, category, filename, lineno, line)
2171 logger = getLogger("py.warnings")
2172 if not logger.handlers:
2173 logger.addHandler(NullHandler())
2174 logger.warning("%s", s)
2176def captureWarnings(capture):
2177 """
2178 If capture is true, redirect all warnings to the logging package.
2179 If capture is False, ensure that warnings are not redirected to logging
2180 but to their original destinations.
2181 """
2182 global _warnings_showwarning
2183 if capture:
2184 if _warnings_showwarning is None:
2185 _warnings_showwarning = warnings.showwarning
2186 warnings.showwarning = _showwarning
2187 else:
2188 if _warnings_showwarning is not None:
2189 warnings.showwarning = _warnings_showwarning
2190 _warnings_showwarning = None