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