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