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