1# Copyright 2001-2010 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, and influenced by Apache's log4j system. 20 21Copyright (C) 2001-2010 Vinay Sajip. All Rights Reserved. 22 23To use, simply 'import logging' and log away! 24""" 25 26import 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 36try: 37 import codecs 38except ImportError: 39 codecs = None 40 41try: 42 import thread 43 import threading 44except ImportError: 45 thread = None 46 47__author__ = "Vinay Sajip <vinay_sajip@red-dove.com>" 48__status__ = "production" 49__version__ = "0.5.1.2" 50__date__ = "07 February 2010" 51 52#--------------------------------------------------------------------------- 53# Miscellaneous module data 54#--------------------------------------------------------------------------- 55try: 56 unicode 57 _unicode = True 58except 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# 65if hasattr(sys, 'frozen'): #support for py2exe 66 _srcfile = "logging%s__init__%s" % (os.sep, __file__[-4:]) 67elif __file__[-4:].lower() in ['.pyc', '.pyo']: 68 _srcfile = __file__[:-4] + '.py' 69else: 70 _srcfile = __file__ 71_srcfile = os.path.normcase(_srcfile) 72 73# next bit filched from 1.5.2's inspect.py 74def 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 81if 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# 100raiseExceptions = 1 101 102# 103# If you don't want threading information in the log, set this to zero 104# 105logThreads = 1 106 107# 108# If you don't want multiprocessing information in the log, set this to zero 109# 110logMultiprocessing = 1 111 112# 113# If you don't want process information in the log, set this to zero 114# 115logProcesses = 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 128CRITICAL = 50 129FATAL = CRITICAL 130ERROR = 40 131WARNING = 30 132WARN = WARNING 133INFO = 20 134DEBUG = 10 135NOTSET = 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 153def 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 169def 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 182def _checkLevel(level): 183 if isinstance(level, int): 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# 205if thread: 206 _lock = threading.RLock() 207else: 208 _lock = None 209 210def _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 219def _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 230class 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 331def 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 346class 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 s = s + record.exc_text.decode(sys.getfilesystemencoding()) 483 return s 484 485# 486# The default formatter to use when no other is specified 487# 488_defaultFormatter = Formatter() 489 490class BufferingFormatter(object): 491 """ 492 A formatter suitable for formatting a number of records. 493 """ 494 def __init__(self, linefmt=None): 495 """ 496 Optionally specify a formatter which will be used to format each 497 individual record. 498 """ 499 if linefmt: 500 self.linefmt = linefmt 501 else: 502 self.linefmt = _defaultFormatter 503 504 def formatHeader(self, records): 505 """ 506 Return the header string for the specified records. 507 """ 508 return "" 509 510 def formatFooter(self, records): 511 """ 512 Return the footer string for the specified records. 513 """ 514 return "" 515 516 def format(self, records): 517 """ 518 Format the specified records and return the result as a string. 519 """ 520 rv = "" 521 if len(records) > 0: 522 rv = rv + self.formatHeader(records) 523 for record in records: 524 rv = rv + self.linefmt.format(record) 525 rv = rv + self.formatFooter(records) 526 return rv 527 528#--------------------------------------------------------------------------- 529# Filter classes and functions 530#--------------------------------------------------------------------------- 531 532class Filter(object): 533 """ 534 Filter instances are used to perform arbitrary filtering of LogRecords. 535 536 Loggers and Handlers can optionally use Filter instances to filter 537 records as desired. The base filter class only allows events which are 538 below a certain point in the logger hierarchy. For example, a filter 539 initialized with "A.B" will allow events logged by loggers "A.B", 540 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If 541 initialized with the empty string, all events are passed. 542 """ 543 def __init__(self, name=''): 544 """ 545 Initialize a filter. 546 547 Initialize with the name of the logger which, together with its 548 children, will have its events allowed through the filter. If no 549 name is specified, allow every event. 550 """ 551 self.name = name 552 self.nlen = len(name) 553 554 def filter(self, record): 555 """ 556 Determine if the specified record is to be logged. 557 558 Is the specified record to be logged? Returns 0 for no, nonzero for 559 yes. If deemed appropriate, the record may be modified in-place. 560 """ 561 if self.nlen == 0: 562 return 1 563 elif self.name == record.name: 564 return 1 565 elif record.name.find(self.name, 0, self.nlen) != 0: 566 return 0 567 return (record.name[self.nlen] == ".") 568 569class Filterer(object): 570 """ 571 A base class for loggers and handlers which allows them to share 572 common code. 573 """ 574 def __init__(self): 575 """ 576 Initialize the list of filters to be an empty list. 577 """ 578 self.filters = [] 579 580 def addFilter(self, filter): 581 """ 582 Add the specified filter to this handler. 583 """ 584 if not (filter in self.filters): 585 self.filters.append(filter) 586 587 def removeFilter(self, filter): 588 """ 589 Remove the specified filter from this handler. 590 """ 591 if filter in self.filters: 592 self.filters.remove(filter) 593 594 def filter(self, record): 595 """ 596 Determine if a record is loggable by consulting all the filters. 597 598 The default is to allow the record to be logged; any filter can veto 599 this and the record is then dropped. Returns a zero value if a record 600 is to be dropped, else non-zero. 601 """ 602 rv = 1 603 for f in self.filters: 604 if not f.filter(record): 605 rv = 0 606 break 607 return rv 608 609#--------------------------------------------------------------------------- 610# Handler classes and functions 611#--------------------------------------------------------------------------- 612 613_handlers = weakref.WeakValueDictionary() #map of handler names to handlers 614_handlerList = [] # added to allow handlers to be removed in reverse of order initialized 615 616def _removeHandlerRef(wr): 617 """ 618 Remove a handler reference from the internal cleanup list. 619 """ 620 # This function can be called during module teardown, when globals are 621 # set to None. If _acquireLock is None, assume this is the case and do 622 # nothing. 623 if _acquireLock is not None: 624 _acquireLock() 625 try: 626 if wr in _handlerList: 627 _handlerList.remove(wr) 628 finally: 629 _releaseLock() 630 631def _addHandlerRef(handler): 632 """ 633 Add a handler to the internal cleanup list using a weak reference. 634 """ 635 _acquireLock() 636 try: 637 _handlerList.append(weakref.ref(handler, _removeHandlerRef)) 638 finally: 639 _releaseLock() 640 641class Handler(Filterer): 642 """ 643 Handler instances dispatch logging events to specific destinations. 644 645 The base handler class. Acts as a placeholder which defines the Handler 646 interface. Handlers can optionally use Formatter instances to format 647 records as desired. By default, no formatter is specified; in this case, 648 the 'raw' message as determined by record.message is logged. 649 """ 650 def __init__(self, level=NOTSET): 651 """ 652 Initializes the instance - basically setting the formatter to None 653 and the filter list to empty. 654 """ 655 Filterer.__init__(self) 656 self._name = None 657 self.level = _checkLevel(level) 658 self.formatter = None 659 # Add the handler to the global _handlerList (for cleanup on shutdown) 660 _addHandlerRef(self) 661 self.createLock() 662 663 def get_name(self): 664 return self._name 665 666 def set_name(self, name): 667 _acquireLock() 668 try: 669 if self._name in _handlers: 670 del _handlers[self._name] 671 self._name = name 672 if name: 673 _handlers[name] = self 674 finally: 675 _releaseLock() 676 677 name = property(get_name, set_name) 678 679 def createLock(self): 680 """ 681 Acquire a thread lock for serializing access to the underlying I/O. 682 """ 683 if thread: 684 self.lock = threading.RLock() 685 else: 686 self.lock = None 687 688 def acquire(self): 689 """ 690 Acquire the I/O thread lock. 691 """ 692 if self.lock: 693 self.lock.acquire() 694 695 def release(self): 696 """ 697 Release the I/O thread lock. 698 """ 699 if self.lock: 700 self.lock.release() 701 702 def setLevel(self, level): 703 """ 704 Set the logging level of this handler. 705 """ 706 self.level = _checkLevel(level) 707 708 def format(self, record): 709 """ 710 Format the specified record. 711 712 If a formatter is set, use it. Otherwise, use the default formatter 713 for the module. 714 """ 715 if self.formatter: 716 fmt = self.formatter 717 else: 718 fmt = _defaultFormatter 719 return fmt.format(record) 720 721 def emit(self, record): 722 """ 723 Do whatever it takes to actually log the specified logging record. 724 725 This version is intended to be implemented by subclasses and so 726 raises a NotImplementedError. 727 """ 728 raise NotImplementedError('emit must be implemented ' 729 'by Handler subclasses') 730 731 def handle(self, record): 732 """ 733 Conditionally emit the specified logging record. 734 735 Emission depends on filters which may have been added to the handler. 736 Wrap the actual emission of the record with acquisition/release of 737 the I/O thread lock. Returns whether the filter passed the record for 738 emission. 739 """ 740 rv = self.filter(record) 741 if rv: 742 self.acquire() 743 try: 744 self.emit(record) 745 finally: 746 self.release() 747 return rv 748 749 def setFormatter(self, fmt): 750 """ 751 Set the formatter for this handler. 752 """ 753 self.formatter = fmt 754 755 def flush(self): 756 """ 757 Ensure all logging output has been flushed. 758 759 This version does nothing and is intended to be implemented by 760 subclasses. 761 """ 762 pass 763 764 def close(self): 765 """ 766 Tidy up any resources used by the handler. 767 768 This version removes the handler from an internal map of handlers, 769 _handlers, which is used for handler lookup by name. Subclasses 770 should ensure that this gets called from overridden close() 771 methods. 772 """ 773 #get the module data lock, as we're updating a shared structure. 774 _acquireLock() 775 try: #unlikely to raise an exception, but you never know... 776 if self._name and self._name in _handlers: 777 del _handlers[self._name] 778 finally: 779 _releaseLock() 780 781 def handleError(self, record): 782 """ 783 Handle errors which occur during an emit() call. 784 785 This method should be called from handlers when an exception is 786 encountered during an emit() call. If raiseExceptions is false, 787 exceptions get silently ignored. This is what is mostly wanted 788 for a logging system - most users will not care about errors in 789 the logging system, they are more interested in application errors. 790 You could, however, replace this with a custom handler if you wish. 791 The record which was being processed is passed in to this method. 792 """ 793 if raiseExceptions: 794 ei = sys.exc_info() 795 try: 796 traceback.print_exception(ei[0], ei[1], ei[2], 797 None, sys.stderr) 798 sys.stderr.write('Logged from file %s, line %s\n' % ( 799 record.filename, record.lineno)) 800 except IOError: 801 pass # see issue 5971 802 finally: 803 del ei 804 805class StreamHandler(Handler): 806 """ 807 A handler class which writes logging records, appropriately formatted, 808 to a stream. Note that this class does not close the stream, as 809 sys.stdout or sys.stderr may be used. 810 """ 811 812 def __init__(self, stream=None): 813 """ 814 Initialize the handler. 815 816 If stream is not specified, sys.stderr is used. 817 """ 818 Handler.__init__(self) 819 if stream is None: 820 stream = sys.stderr 821 self.stream = stream 822 823 def flush(self): 824 """ 825 Flushes the stream. 826 """ 827 if self.stream and hasattr(self.stream, "flush"): 828 self.stream.flush() 829 830 def emit(self, record): 831 """ 832 Emit a record. 833 834 If a formatter is specified, it is used to format the record. 835 The record is then written to the stream with a trailing newline. If 836 exception information is present, it is formatted using 837 traceback.print_exception and appended to the stream. If the stream 838 has an 'encoding' attribute, it is used to determine how to do the 839 output to the stream. 840 """ 841 try: 842 msg = self.format(record) 843 stream = self.stream 844 fs = "%s\n" 845 if not _unicode: #if no unicode support... 846 stream.write(fs % msg) 847 else: 848 try: 849 if (isinstance(msg, unicode) and 850 getattr(stream, 'encoding', None)): 851 ufs = fs.decode(stream.encoding) 852 try: 853 stream.write(ufs % msg) 854 except UnicodeEncodeError: 855 #Printing to terminals sometimes fails. For example, 856 #with an encoding of 'cp1251', the above write will 857 #work if written to a stream opened or wrapped by 858 #the codecs module, but fail when writing to a 859 #terminal even when the codepage is set to cp1251. 860 #An extra encoding step seems to be needed. 861 stream.write((ufs % msg).encode(stream.encoding)) 862 else: 863 stream.write(fs % msg) 864 except UnicodeError: 865 stream.write(fs % msg.encode("UTF-8")) 866 self.flush() 867 except (KeyboardInterrupt, SystemExit): 868 raise 869 except: 870 self.handleError(record) 871 872class FileHandler(StreamHandler): 873 """ 874 A handler class which writes formatted logging records to disk files. 875 """ 876 def __init__(self, filename, mode='a', encoding=None, delay=0): 877 """ 878 Open the specified file and use it as the stream for logging. 879 """ 880 #keep the absolute path, otherwise derived classes which use this 881 #may come a cropper when the current directory changes 882 if codecs is None: 883 encoding = None 884 self.baseFilename = os.path.abspath(filename) 885 self.mode = mode 886 self.encoding = encoding 887 if delay: 888 #We don't open the stream, but we still need to call the 889 #Handler constructor to set level, formatter, lock etc. 890 Handler.__init__(self) 891 self.stream = None 892 else: 893 StreamHandler.__init__(self, self._open()) 894 895 def close(self): 896 """ 897 Closes the stream. 898 """ 899 if self.stream: 900 self.flush() 901 if hasattr(self.stream, "close"): 902 self.stream.close() 903 StreamHandler.close(self) 904 self.stream = None 905 906 def _open(self): 907 """ 908 Open the current base file with the (original) mode and encoding. 909 Return the resulting stream. 910 """ 911 if self.encoding is None: 912 stream = open(self.baseFilename, self.mode) 913 else: 914 stream = codecs.open(self.baseFilename, self.mode, self.encoding) 915 return stream 916 917 def emit(self, record): 918 """ 919 Emit a record. 920 921 If the stream was not opened because 'delay' was specified in the 922 constructor, open it before calling the superclass's emit. 923 """ 924 if self.stream is None: 925 self.stream = self._open() 926 StreamHandler.emit(self, record) 927 928#--------------------------------------------------------------------------- 929# Manager classes and functions 930#--------------------------------------------------------------------------- 931 932class PlaceHolder(object): 933 """ 934 PlaceHolder instances are used in the Manager logger hierarchy to take 935 the place of nodes for which no loggers have been defined. This class is 936 intended for internal use only and not as part of the public API. 937 """ 938 def __init__(self, alogger): 939 """ 940 Initialize with the specified logger being a child of this placeholder. 941 """ 942 #self.loggers = [alogger] 943 self.loggerMap = { alogger : None } 944 945 def append(self, alogger): 946 """ 947 Add the specified logger as a child of this placeholder. 948 """ 949 #if alogger not in self.loggers: 950 if alogger not in self.loggerMap: 951 #self.loggers.append(alogger) 952 self.loggerMap[alogger] = None 953 954# 955# Determine which class to use when instantiating loggers. 956# 957_loggerClass = None 958 959def setLoggerClass(klass): 960 """ 961 Set the class to be used when instantiating a logger. The class should 962 define __init__() such that only a name argument is required, and the 963 __init__() should call Logger.__init__() 964 """ 965 if klass != Logger: 966 if not issubclass(klass, Logger): 967 raise TypeError("logger not derived from logging.Logger: " 968 + klass.__name__) 969 global _loggerClass 970 _loggerClass = klass 971 972def getLoggerClass(): 973 """ 974 Return the class to be used when instantiating a logger. 975 """ 976 977 return _loggerClass 978 979class Manager(object): 980 """ 981 There is [under normal circumstances] just one Manager instance, which 982 holds the hierarchy of loggers. 983 """ 984 def __init__(self, rootnode): 985 """ 986 Initialize the manager with the root node of the logger hierarchy. 987 """ 988 self.root = rootnode 989 self.disable = 0 990 self.emittedNoHandlerWarning = 0 991 self.loggerDict = {} 992 self.loggerClass = None 993 994 def getLogger(self, name): 995 """ 996 Get a logger with the specified name (channel name), creating it 997 if it doesn't yet exist. This name is a dot-separated hierarchical 998 name, such as "a", "a.b", "a.b.c" or similar. 999 1000 If a PlaceHolder existed for the specified name [i.e. the logger 1001 didn't exist but a child of it did], replace it with the created 1002 logger and fix up the parent/child references which pointed to the 1003 placeholder to now point to the logger. 1004 """ 1005 rv = None 1006 _acquireLock() 1007 try: 1008 if name in self.loggerDict: 1009 rv = self.loggerDict[name] 1010 if isinstance(rv, PlaceHolder): 1011 ph = rv 1012 rv = (self.loggerClass or _loggerClass)(name) 1013 rv.manager = self 1014 self.loggerDict[name] = rv 1015 self._fixupChildren(ph, rv) 1016 self._fixupParents(rv) 1017 else: 1018 rv = (self.loggerClass or _loggerClass)(name) 1019 rv.manager = self 1020 self.loggerDict[name] = rv 1021 self._fixupParents(rv) 1022 finally: 1023 _releaseLock() 1024 return rv 1025 1026 def setLoggerClass(self, klass): 1027 """ 1028 Set the class to be used when instantiating a logger with this Manager. 1029 """ 1030 if klass != Logger: 1031 if not issubclass(klass, Logger): 1032 raise TypeError("logger not derived from logging.Logger: " 1033 + klass.__name__) 1034 self.loggerClass = klass 1035 1036 def _fixupParents(self, alogger): 1037 """ 1038 Ensure that there are either loggers or placeholders all the way 1039 from the specified logger to the root of the logger hierarchy. 1040 """ 1041 name = alogger.name 1042 i = name.rfind(".") 1043 rv = None 1044 while (i > 0) and not rv: 1045 substr = name[:i] 1046 if substr not in self.loggerDict: 1047 self.loggerDict[substr] = PlaceHolder(alogger) 1048 else: 1049 obj = self.loggerDict[substr] 1050 if isinstance(obj, Logger): 1051 rv = obj 1052 else: 1053 assert isinstance(obj, PlaceHolder) 1054 obj.append(alogger) 1055 i = name.rfind(".", 0, i - 1) 1056 if not rv: 1057 rv = self.root 1058 alogger.parent = rv 1059 1060 def _fixupChildren(self, ph, alogger): 1061 """ 1062 Ensure that children of the placeholder ph are connected to the 1063 specified logger. 1064 """ 1065 name = alogger.name 1066 namelen = len(name) 1067 for c in ph.loggerMap.keys(): 1068 #The if means ... if not c.parent.name.startswith(nm) 1069 if c.parent.name[:namelen] != name: 1070 alogger.parent = c.parent 1071 c.parent = alogger 1072 1073#--------------------------------------------------------------------------- 1074# Logger classes and functions 1075#--------------------------------------------------------------------------- 1076 1077class Logger(Filterer): 1078 """ 1079 Instances of the Logger class represent a single logging channel. A 1080 "logging channel" indicates an area of an application. Exactly how an 1081 "area" is defined is up to the application developer. Since an 1082 application can have any number of areas, logging channels are identified 1083 by a unique string. Application areas can be nested (e.g. an area 1084 of "input processing" might include sub-areas "read CSV files", "read 1085 XLS files" and "read Gnumeric files"). To cater for this natural nesting, 1086 channel names are organized into a namespace hierarchy where levels are 1087 separated by periods, much like the Java or Python package namespace. So 1088 in the instance given above, channel names might be "input" for the upper 1089 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels. 1090 There is no arbitrary limit to the depth of nesting. 1091 """ 1092 def __init__(self, name, level=NOTSET): 1093 """ 1094 Initialize the logger with a name and an optional level. 1095 """ 1096 Filterer.__init__(self) 1097 self.name = name 1098 self.level = _checkLevel(level) 1099 self.parent = None 1100 self.propagate = 1 1101 self.handlers = [] 1102 self.disabled = 0 1103 1104 def setLevel(self, level): 1105 """ 1106 Set the logging level of this logger. 1107 """ 1108 self.level = _checkLevel(level) 1109 1110 def debug(self, msg, *args, **kwargs): 1111 """ 1112 Log 'msg % args' with severity 'DEBUG'. 1113 1114 To pass exception information, use the keyword argument exc_info with 1115 a true value, e.g. 1116 1117 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1) 1118 """ 1119 if self.isEnabledFor(DEBUG): 1120 self._log(DEBUG, msg, args, **kwargs) 1121 1122 def info(self, msg, *args, **kwargs): 1123 """ 1124 Log 'msg % args' with severity 'INFO'. 1125 1126 To pass exception information, use the keyword argument exc_info with 1127 a true value, e.g. 1128 1129 logger.info("Houston, we have a %s", "interesting problem", exc_info=1) 1130 """ 1131 if self.isEnabledFor(INFO): 1132 self._log(INFO, msg, args, **kwargs) 1133 1134 def warning(self, msg, *args, **kwargs): 1135 """ 1136 Log 'msg % args' with severity 'WARNING'. 1137 1138 To pass exception information, use the keyword argument exc_info with 1139 a true value, e.g. 1140 1141 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1) 1142 """ 1143 if self.isEnabledFor(WARNING): 1144 self._log(WARNING, msg, args, **kwargs) 1145 1146 warn = warning 1147 1148 def error(self, msg, *args, **kwargs): 1149 """ 1150 Log 'msg % args' with severity 'ERROR'. 1151 1152 To pass exception information, use the keyword argument exc_info with 1153 a true value, e.g. 1154 1155 logger.error("Houston, we have a %s", "major problem", exc_info=1) 1156 """ 1157 if self.isEnabledFor(ERROR): 1158 self._log(ERROR, msg, args, **kwargs) 1159 1160 def exception(self, msg, *args): 1161 """ 1162 Convenience method for logging an ERROR with exception information. 1163 """ 1164 self.error(msg, exc_info=1, *args) 1165 1166 def critical(self, msg, *args, **kwargs): 1167 """ 1168 Log 'msg % args' with severity 'CRITICAL'. 1169 1170 To pass exception information, use the keyword argument exc_info with 1171 a true value, e.g. 1172 1173 logger.critical("Houston, we have a %s", "major disaster", exc_info=1) 1174 """ 1175 if self.isEnabledFor(CRITICAL): 1176 self._log(CRITICAL, msg, args, **kwargs) 1177 1178 fatal = critical 1179 1180 def log(self, level, msg, *args, **kwargs): 1181 """ 1182 Log 'msg % args' with the integer severity 'level'. 1183 1184 To pass exception information, use the keyword argument exc_info with 1185 a true value, e.g. 1186 1187 logger.log(level, "We have a %s", "mysterious problem", exc_info=1) 1188 """ 1189 if not isinstance(level, int): 1190 if raiseExceptions: 1191 raise TypeError("level must be an integer") 1192 else: 1193 return 1194 if self.isEnabledFor(level): 1195 self._log(level, msg, args, **kwargs) 1196 1197 def findCaller(self): 1198 """ 1199 Find the stack frame of the caller so that we can note the source 1200 file name, line number and function name. 1201 """ 1202 f = currentframe() 1203 #On some versions of IronPython, currentframe() returns None if 1204 #IronPython isn't run with -X:Frames. 1205 if f is not None: 1206 f = f.f_back 1207 rv = "(unknown file)", 0, "(unknown function)" 1208 while hasattr(f, "f_code"): 1209 co = f.f_code 1210 filename = os.path.normcase(co.co_filename) 1211 if filename == _srcfile: 1212 f = f.f_back 1213 continue 1214 rv = (co.co_filename, f.f_lineno, co.co_name) 1215 break 1216 return rv 1217 1218 def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None): 1219 """ 1220 A factory method which can be overridden in subclasses to create 1221 specialized LogRecords. 1222 """ 1223 rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func) 1224 if extra is not None: 1225 for key in extra: 1226 if (key in ["message", "asctime"]) or (key in rv.__dict__): 1227 raise KeyError("Attempt to overwrite %r in LogRecord" % key) 1228 rv.__dict__[key] = extra[key] 1229 return rv 1230 1231 def _log(self, level, msg, args, exc_info=None, extra=None): 1232 """ 1233 Low-level logging routine which creates a LogRecord and then calls 1234 all the handlers of this logger to handle the record. 1235 """ 1236 if _srcfile: 1237 #IronPython doesn't track Python frames, so findCaller throws an 1238 #exception on some versions of IronPython. We trap it here so that 1239 #IronPython can use logging. 1240 try: 1241 fn, lno, func = self.findCaller() 1242 except ValueError: 1243 fn, lno, func = "(unknown file)", 0, "(unknown function)" 1244 else: 1245 fn, lno, func = "(unknown file)", 0, "(unknown function)" 1246 if exc_info: 1247 if not isinstance(exc_info, tuple): 1248 exc_info = sys.exc_info() 1249 record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra) 1250 self.handle(record) 1251 1252 def handle(self, record): 1253 """ 1254 Call the handlers for the specified record. 1255 1256 This method is used for unpickled records received from a socket, as 1257 well as those created locally. Logger-level filtering is applied. 1258 """ 1259 if (not self.disabled) and self.filter(record): 1260 self.callHandlers(record) 1261 1262 def addHandler(self, hdlr): 1263 """ 1264 Add the specified handler to this logger. 1265 """ 1266 _acquireLock() 1267 try: 1268 if not (hdlr in self.handlers): 1269 self.handlers.append(hdlr) 1270 finally: 1271 _releaseLock() 1272 1273 def removeHandler(self, hdlr): 1274 """ 1275 Remove the specified handler from this logger. 1276 """ 1277 _acquireLock() 1278 try: 1279 if hdlr in self.handlers: 1280 self.handlers.remove(hdlr) 1281 finally: 1282 _releaseLock() 1283 1284 def callHandlers(self, record): 1285 """ 1286 Pass a record to all relevant handlers. 1287 1288 Loop through all handlers for this logger and its parents in the 1289 logger hierarchy. If no handler was found, output a one-off error 1290 message to sys.stderr. Stop searching up the hierarchy whenever a 1291 logger with the "propagate" attribute set to zero is found - that 1292 will be the last logger whose handlers are called. 1293 """ 1294 c = self 1295 found = 0 1296 while c: 1297 for hdlr in c.handlers: 1298 found = found + 1 1299 if record.levelno >= hdlr.level: 1300 hdlr.handle(record) 1301 if not c.propagate: 1302 c = None #break out 1303 else: 1304 c = c.parent 1305 if (found == 0) and raiseExceptions and not self.manager.emittedNoHandlerWarning: 1306 sys.stderr.write("No handlers could be found for logger" 1307 " \"%s\"\n" % self.name) 1308 self.manager.emittedNoHandlerWarning = 1 1309 1310 def getEffectiveLevel(self): 1311 """ 1312 Get the effective level for this logger. 1313 1314 Loop through this logger and its parents in the logger hierarchy, 1315 looking for a non-zero logging level. Return the first one found. 1316 """ 1317 logger = self 1318 while logger: 1319 if logger.level: 1320 return logger.level 1321 logger = logger.parent 1322 return NOTSET 1323 1324 def isEnabledFor(self, level): 1325 """ 1326 Is this logger enabled for level 'level'? 1327 """ 1328 if self.manager.disable >= level: 1329 return 0 1330 return level >= self.getEffectiveLevel() 1331 1332 def getChild(self, suffix): 1333 """ 1334 Get a logger which is a descendant to this one. 1335 1336 This is a convenience method, such that 1337 1338 logging.getLogger('abc').getChild('def.ghi') 1339 1340 is the same as 1341 1342 logging.getLogger('abc.def.ghi') 1343 1344 It's useful, for example, when the parent logger is named using 1345 __name__ rather than a literal string. 1346 """ 1347 if self.root is not self: 1348 suffix = '.'.join((self.name, suffix)) 1349 return self.manager.getLogger(suffix) 1350 1351class RootLogger(Logger): 1352 """ 1353 A root logger is not that different to any other logger, except that 1354 it must have a logging level and there is only one instance of it in 1355 the hierarchy. 1356 """ 1357 def __init__(self, level): 1358 """ 1359 Initialize the logger with the name "root". 1360 """ 1361 Logger.__init__(self, "root", level) 1362 1363_loggerClass = Logger 1364 1365class LoggerAdapter(object): 1366 """ 1367 An adapter for loggers which makes it easier to specify contextual 1368 information in logging output. 1369 """ 1370 1371 def __init__(self, logger, extra): 1372 """ 1373 Initialize the adapter with a logger and a dict-like object which 1374 provides contextual information. This constructor signature allows 1375 easy stacking of LoggerAdapters, if so desired. 1376 1377 You can effectively pass keyword arguments as shown in the 1378 following example: 1379 1380 adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2")) 1381 """ 1382 self.logger = logger 1383 self.extra = extra 1384 1385 def process(self, msg, kwargs): 1386 """ 1387 Process the logging message and keyword arguments passed in to 1388 a logging call to insert contextual information. You can either 1389 manipulate the message itself, the keyword args or both. Return 1390 the message and kwargs modified (or not) to suit your needs. 1391 1392 Normally, you'll only need to override this one method in a 1393 LoggerAdapter subclass for your specific needs. 1394 """ 1395 kwargs["extra"] = self.extra 1396 return msg, kwargs 1397 1398 def debug(self, msg, *args, **kwargs): 1399 """ 1400 Delegate a debug call to the underlying logger, after adding 1401 contextual information from this adapter instance. 1402 """ 1403 msg, kwargs = self.process(msg, kwargs) 1404 self.logger.debug(msg, *args, **kwargs) 1405 1406 def info(self, msg, *args, **kwargs): 1407 """ 1408 Delegate an info call to the underlying logger, after adding 1409 contextual information from this adapter instance. 1410 """ 1411 msg, kwargs = self.process(msg, kwargs) 1412 self.logger.info(msg, *args, **kwargs) 1413 1414 def warning(self, msg, *args, **kwargs): 1415 """ 1416 Delegate a warning call to the underlying logger, after adding 1417 contextual information from this adapter instance. 1418 """ 1419 msg, kwargs = self.process(msg, kwargs) 1420 self.logger.warning(msg, *args, **kwargs) 1421 1422 def error(self, msg, *args, **kwargs): 1423 """ 1424 Delegate an error call to the underlying logger, after adding 1425 contextual information from this adapter instance. 1426 """ 1427 msg, kwargs = self.process(msg, kwargs) 1428 self.logger.error(msg, *args, **kwargs) 1429 1430 def exception(self, msg, *args, **kwargs): 1431 """ 1432 Delegate an exception call to the underlying logger, after adding 1433 contextual information from this adapter instance. 1434 """ 1435 msg, kwargs = self.process(msg, kwargs) 1436 kwargs["exc_info"] = 1 1437 self.logger.error(msg, *args, **kwargs) 1438 1439 def critical(self, msg, *args, **kwargs): 1440 """ 1441 Delegate a critical call to the underlying logger, after adding 1442 contextual information from this adapter instance. 1443 """ 1444 msg, kwargs = self.process(msg, kwargs) 1445 self.logger.critical(msg, *args, **kwargs) 1446 1447 def log(self, level, msg, *args, **kwargs): 1448 """ 1449 Delegate a log call to the underlying logger, after adding 1450 contextual information from this adapter instance. 1451 """ 1452 msg, kwargs = self.process(msg, kwargs) 1453 self.logger.log(level, msg, *args, **kwargs) 1454 1455 def isEnabledFor(self, level): 1456 """ 1457 See if the underlying logger is enabled for the specified level. 1458 """ 1459 return self.logger.isEnabledFor(level) 1460 1461root = RootLogger(WARNING) 1462Logger.root = root 1463Logger.manager = Manager(Logger.root) 1464 1465#--------------------------------------------------------------------------- 1466# Configuration classes and functions 1467#--------------------------------------------------------------------------- 1468 1469BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s" 1470 1471def basicConfig(**kwargs): 1472 """ 1473 Do basic configuration for the logging system. 1474 1475 This function does nothing if the root logger already has handlers 1476 configured. It is a convenience method intended for use by simple scripts 1477 to do one-shot configuration of the logging package. 1478 1479 The default behaviour is to create a StreamHandler which writes to 1480 sys.stderr, set a formatter using the BASIC_FORMAT format string, and 1481 add the handler to the root logger. 1482 1483 A number of optional keyword arguments may be specified, which can alter 1484 the default behaviour. 1485 1486 filename Specifies that a FileHandler be created, using the specified 1487 filename, rather than a StreamHandler. 1488 filemode Specifies the mode to open the file, if filename is specified 1489 (if filemode is unspecified, it defaults to 'a'). 1490 format Use the specified format string for the handler. 1491 datefmt Use the specified date/time format. 1492 level Set the root logger level to the specified level. 1493 stream Use the specified stream to initialize the StreamHandler. Note 1494 that this argument is incompatible with 'filename' - if both 1495 are present, 'stream' is ignored. 1496 1497 Note that you could specify a stream created using open(filename, mode) 1498 rather than passing the filename and mode in. However, it should be 1499 remembered that StreamHandler does not close its stream (since it may be 1500 using sys.stdout or sys.stderr), whereas FileHandler closes its stream 1501 when the handler is closed. 1502 """ 1503 # Add thread safety in case someone mistakenly calls 1504 # basicConfig() from multiple threads 1505 _acquireLock() 1506 try: 1507 if len(root.handlers) == 0: 1508 filename = kwargs.get("filename") 1509 if filename: 1510 mode = kwargs.get("filemode", 'a') 1511 hdlr = FileHandler(filename, mode) 1512 else: 1513 stream = kwargs.get("stream") 1514 hdlr = StreamHandler(stream) 1515 fs = kwargs.get("format", BASIC_FORMAT) 1516 dfs = kwargs.get("datefmt", None) 1517 fmt = Formatter(fs, dfs) 1518 hdlr.setFormatter(fmt) 1519 root.addHandler(hdlr) 1520 level = kwargs.get("level") 1521 if level is not None: 1522 root.setLevel(level) 1523 finally: 1524 _releaseLock() 1525 1526#--------------------------------------------------------------------------- 1527# Utility functions at module level. 1528# Basically delegate everything to the root logger. 1529#--------------------------------------------------------------------------- 1530 1531def getLogger(name=None): 1532 """ 1533 Return a logger with the specified name, creating it if necessary. 1534 1535 If no name is specified, return the root logger. 1536 """ 1537 if name: 1538 return Logger.manager.getLogger(name) 1539 else: 1540 return root 1541 1542#def getRootLogger(): 1543# """ 1544# Return the root logger. 1545# 1546# Note that getLogger('') now does the same thing, so this function is 1547# deprecated and may disappear in the future. 1548# """ 1549# return root 1550 1551def critical(msg, *args, **kwargs): 1552 """ 1553 Log a message with severity 'CRITICAL' on the root logger. 1554 """ 1555 if len(root.handlers) == 0: 1556 basicConfig() 1557 root.critical(msg, *args, **kwargs) 1558 1559fatal = critical 1560 1561def error(msg, *args, **kwargs): 1562 """ 1563 Log a message with severity 'ERROR' on the root logger. 1564 """ 1565 if len(root.handlers) == 0: 1566 basicConfig() 1567 root.error(msg, *args, **kwargs) 1568 1569def exception(msg, *args): 1570 """ 1571 Log a message with severity 'ERROR' on the root logger, 1572 with exception information. 1573 """ 1574 error(msg, exc_info=1, *args) 1575 1576def warning(msg, *args, **kwargs): 1577 """ 1578 Log a message with severity 'WARNING' on the root logger. 1579 """ 1580 if len(root.handlers) == 0: 1581 basicConfig() 1582 root.warning(msg, *args, **kwargs) 1583 1584warn = warning 1585 1586def info(msg, *args, **kwargs): 1587 """ 1588 Log a message with severity 'INFO' on the root logger. 1589 """ 1590 if len(root.handlers) == 0: 1591 basicConfig() 1592 root.info(msg, *args, **kwargs) 1593 1594def debug(msg, *args, **kwargs): 1595 """ 1596 Log a message with severity 'DEBUG' on the root logger. 1597 """ 1598 if len(root.handlers) == 0: 1599 basicConfig() 1600 root.debug(msg, *args, **kwargs) 1601 1602def log(level, msg, *args, **kwargs): 1603 """ 1604 Log 'msg % args' with the integer severity 'level' on the root logger. 1605 """ 1606 if len(root.handlers) == 0: 1607 basicConfig() 1608 root.log(level, msg, *args, **kwargs) 1609 1610def disable(level): 1611 """ 1612 Disable all logging calls of severity 'level' and below. 1613 """ 1614 root.manager.disable = level 1615 1616def shutdown(handlerList=_handlerList): 1617 """ 1618 Perform any cleanup actions in the logging system (e.g. flushing 1619 buffers). 1620 1621 Should be called at application exit. 1622 """ 1623 for wr in reversed(handlerList[:]): 1624 #errors might occur, for example, if files are locked 1625 #we just ignore them if raiseExceptions is not set 1626 try: 1627 h = wr() 1628 if h: 1629 try: 1630 h.acquire() 1631 h.flush() 1632 h.close() 1633 except (IOError, ValueError): 1634 # Ignore errors which might be caused 1635 # because handlers have been closed but 1636 # references to them are still around at 1637 # application exit. 1638 pass 1639 finally: 1640 h.release() 1641 except: 1642 if raiseExceptions: 1643 raise 1644 #else, swallow 1645 1646#Let's try and shutdown automatically on application exit... 1647import atexit 1648atexit.register(shutdown) 1649 1650# Null handler 1651 1652class NullHandler(Handler): 1653 """ 1654 This handler does nothing. It's intended to be used to avoid the 1655 "No handlers could be found for logger XXX" one-off warning. This is 1656 important for library code, which may contain code to log events. If a user 1657 of the library does not configure logging, the one-off warning might be 1658 produced; to avoid this, the library developer simply needs to instantiate 1659 a NullHandler and add it to the top-level logger of the library module or 1660 package. 1661 """ 1662 def handle(self, record): 1663 pass 1664 1665 def emit(self, record): 1666 pass 1667 1668 def createLock(self): 1669 self.lock = None 1670 1671# Warnings integration 1672 1673_warnings_showwarning = None 1674 1675def _showwarning(message, category, filename, lineno, file=None, line=None): 1676 """ 1677 Implementation of showwarnings which redirects to logging, which will first 1678 check to see if the file parameter is None. If a file is specified, it will 1679 delegate to the original warnings implementation of showwarning. Otherwise, 1680 it will call warnings.formatwarning and will log the resulting string to a 1681 warnings logger named "py.warnings" with level logging.WARNING. 1682 """ 1683 if file is not None: 1684 if _warnings_showwarning is not None: 1685 _warnings_showwarning(message, category, filename, lineno, file, line) 1686 else: 1687 s = warnings.formatwarning(message, category, filename, lineno, line) 1688 logger = getLogger("py.warnings") 1689 if not logger.handlers: 1690 logger.addHandler(NullHandler()) 1691 logger.warning("%s", s) 1692 1693def captureWarnings(capture): 1694 """ 1695 If capture is true, redirect all warnings to the logging package. 1696 If capture is False, ensure that warnings are not redirected to logging 1697 but to their original destinations. 1698 """ 1699 global _warnings_showwarning 1700 if capture: 1701 if _warnings_showwarning is None: 1702 _warnings_showwarning = warnings.showwarning 1703 warnings.showwarning = _showwarning 1704 else: 1705 if _warnings_showwarning is not None: 1706 warnings.showwarning = _warnings_showwarning 1707 _warnings_showwarning = None 1708