PageRenderTime 267ms CodeModel.GetById 16ms app.highlight 216ms RepoModel.GetById 2ms app.codeStats 0ms

/Lib/logging/__init__.py

http://unladen-swallow.googlecode.com/
Python | 1526 lines | 1500 code | 4 blank | 22 comment | 6 complexity | 0e8e58c34832978e6f2101476931ab5f MD5 | raw file

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file