home *** CD-ROM | disk | FTP | other *** search
- # Source Generated with Decompyle++
- # File: in.pyc (Python 2.4)
-
- """
- Logging package for Python. Based on PEP 282 and comments thereto in
- comp.lang.python, and influenced by Apache's log4j system.
-
- Should work under Python versions >= 1.5.2, except that source line
- information is not available unless 'sys._getframe()' is.
-
- Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
-
- To use, simply 'import logging' and log away!
- """
- import sys
- import os
- import types
- import time
- import string
- import cStringIO
-
- try:
- import thread
- import threading
- except ImportError:
- thread = None
-
- __author__ = 'Vinay Sajip <vinay_sajip@red-dove.com>'
- __status__ = 'beta'
- __version__ = '0.4.9.6'
- __date__ = '20 October 2004'
- if string.lower(__file__[-4:]) in [
- '.pyc',
- '.pyo']:
- _srcfile = __file__[:-4] + '.py'
- else:
- _srcfile = __file__
- _srcfile = os.path.normcase(_srcfile)
- if not hasattr(sys, '_getframe'):
- _srcfile = None
-
- _startTime = time.time()
- raiseExceptions = 1
- CRITICAL = 50
- FATAL = CRITICAL
- ERROR = 40
- WARNING = 30
- WARN = WARNING
- INFO = 20
- DEBUG = 10
- NOTSET = 0
- _levelNames = {
- CRITICAL: 'CRITICAL',
- ERROR: 'ERROR',
- WARNING: 'WARNING',
- INFO: 'INFO',
- DEBUG: 'DEBUG',
- NOTSET: 'NOTSET',
- 'CRITICAL': CRITICAL,
- 'ERROR': ERROR,
- 'WARN': WARNING,
- 'WARNING': WARNING,
- 'INFO': INFO,
- 'DEBUG': DEBUG,
- 'NOTSET': NOTSET }
-
- def getLevelName(level):
- '''
- Return the textual representation of logging level \'level\'.
-
- If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
- INFO, DEBUG) then you get the corresponding string. If you have
- associated levels with names using addLevelName then the name you have
- associated with \'level\' is returned.
-
- If a numeric value corresponding to one of the defined levels is passed
- in, the corresponding string representation is returned.
-
- Otherwise, the string "Level %s" % level is returned.
- '''
- return _levelNames.get(level, 'Level %s' % level)
-
-
- def addLevelName(level, levelName):
- """
- Associate 'levelName' with 'level'.
-
- This is used when converting levels to text during message formatting.
- """
- _acquireLock()
-
- try:
- _levelNames[level] = levelName
- _levelNames[levelName] = level
- finally:
- _releaseLock()
-
-
- _lock = None
-
- def _acquireLock():
- '''
- Acquire the module-level lock for serializing access to shared data.
-
- This should be released with _releaseLock().
- '''
- global _lock
- if not _lock and thread:
- _lock = threading.RLock()
-
- if _lock:
- _lock.acquire()
-
-
-
- def _releaseLock():
- '''
- Release the module-level lock acquired by calling _acquireLock().
- '''
- if _lock:
- _lock.release()
-
-
-
- class LogRecord:
- '''
- A LogRecord instance represents an event being logged.
-
- LogRecord instances are created every time something is logged. They
- contain all the information pertinent to the event being logged. The
- main information passed in is in msg and args, which are combined
- using str(msg) % args to create the message field of the record. The
- record also includes information such as when the record was created,
- the source line where the logging call was made, and any exception
- information to be logged.
- '''
-
- def __init__(self, name, level, pathname, lineno, msg, args, exc_info):
- '''
- Initialize a logging record with interesting information.
- '''
- ct = time.time()
- self.name = name
- self.msg = msg
- if args and len(args) == 1 and args[0] and type(args[0]) == types.DictType:
- args = args[0]
-
- self.args = args
- self.levelname = getLevelName(level)
- self.levelno = level
- self.pathname = pathname
-
- try:
- self.filename = os.path.basename(pathname)
- self.module = os.path.splitext(self.filename)[0]
- except:
- self.filename = pathname
- self.module = 'Unknown module'
-
- self.exc_info = exc_info
- self.exc_text = None
- self.lineno = lineno
- self.created = ct
- self.msecs = (ct - long(ct)) * 1000
- self.relativeCreated = (self.created - _startTime) * 1000
- if thread:
- self.thread = thread.get_ident()
- else:
- self.thread = None
- if hasattr(os, 'getpid'):
- self.process = os.getpid()
- else:
- self.process = None
-
-
- def __str__(self):
- return '<LogRecord: %s, %s, %s, %s, "%s">' % (self.name, self.levelno, self.pathname, self.lineno, self.msg)
-
-
- def getMessage(self):
- '''
- Return the message for this LogRecord.
-
- Return the message for this LogRecord after merging any user-supplied
- arguments with the message.
- '''
- if not hasattr(types, 'UnicodeType'):
- msg = str(self.msg)
- else:
-
- try:
- msg = str(self.msg)
- except UnicodeError:
- msg = self.msg
-
- if self.args:
- msg = msg % self.args
-
- return msg
-
-
-
- def makeLogRecord(dict):
- '''
- Make a LogRecord whose attributes are defined by the specified dictionary,
- This function is useful for converting a logging event received over
- a socket connection (which is sent as a dictionary) into a LogRecord
- instance.
- '''
- rv = LogRecord(None, None, '', 0, '', (), None)
- rv.__dict__.update(dict)
- return rv
-
-
- class Formatter:
- '''
- Formatter instances are used to convert a LogRecord to text.
-
- Formatters need to know how a LogRecord is constructed. They are
- responsible for converting a LogRecord to (usually) a string which can
- be interpreted by either a human or an external system. The base Formatter
- allows a formatting string to be specified. If none is supplied, the
- default value of "%s(message)\\n" is used.
-
- The Formatter can be initialized with a format string which makes use of
- knowledge of the LogRecord attributes - e.g. the default value mentioned
- above makes use of the fact that the user\'s message and arguments are pre-
- formatted into a LogRecord\'s message attribute. Currently, the useful
- attributes in a LogRecord are described by:
-
- %(name)s Name of the logger (logging channel)
- %(levelno)s Numeric logging level for the message (DEBUG, INFO,
- WARNING, ERROR, CRITICAL)
- %(levelname)s Text logging level for the message ("DEBUG", "INFO",
- "WARNING", "ERROR", "CRITICAL")
- %(pathname)s Full pathname of the source file where the logging
- call was issued (if available)
- %(filename)s Filename portion of pathname
- %(module)s Module (name portion of filename)
- %(lineno)d Source line number where the logging call was issued
- (if available)
- %(created)f Time when the LogRecord was created (time.time()
- return value)
- %(asctime)s Textual time when the LogRecord was created
- %(msecs)d Millisecond portion of the creation time
- %(relativeCreated)d Time in milliseconds when the LogRecord was created,
- relative to the time the logging module was loaded
- (typically at application startup time)
- %(thread)d Thread ID (if available)
- %(process)d Process ID (if available)
- %(message)s The result of record.getMessage(), computed just as
- the record is emitted
- '''
- converter = time.localtime
-
- def __init__(self, fmt = None, datefmt = None):
- '''
- Initialize the formatter with specified format strings.
-
- Initialize the formatter either with the specified format string, or a
- default as described above. Allow for specialized date formatting with
- the optional datefmt argument (if omitted, you get the ISO8601 format).
- '''
- if fmt:
- self._fmt = fmt
- else:
- self._fmt = '%(message)s'
- self.datefmt = datefmt
-
-
- def formatTime(self, record, datefmt = None):
- """
- Return the creation time of the specified LogRecord as formatted text.
-
- This method should be called from format() by a formatter which
- wants to make use of a formatted time. This method can be overridden
- in formatters to provide for any specific requirement, but the
- basic behaviour is as follows: if datefmt (a string) is specified,
- it is used with time.strftime() to format the creation time of the
- record. Otherwise, the ISO8601 format is used. The resulting
- string is returned. This function uses a user-configurable function
- to convert the creation time to a tuple. By default, time.localtime()
- is used; to change this for a particular formatter instance, set the
- 'converter' attribute to a function with the same signature as
- time.localtime() or time.gmtime(). To change it for all formatters,
- for example if you want all logging times to be shown in GMT,
- set the 'converter' attribute in the Formatter class.
- """
- ct = self.converter(record.created)
- if datefmt:
- s = time.strftime(datefmt, ct)
- else:
- t = time.strftime('%Y-%m-%d %H:%M:%S', ct)
- s = '%s,%03d' % (t, record.msecs)
- return s
-
-
- def formatException(self, ei):
- '''
- Format and return the specified exception information as a string.
-
- This default implementation just uses
- traceback.print_exception()
- '''
- import traceback
- sio = cStringIO.StringIO()
- traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
- s = sio.getvalue()
- sio.close()
- if s[-1] == '\n':
- s = s[:-1]
-
- return s
-
-
- def format(self, record):
- '''
- Format the specified record as text.
-
- The record\'s attribute dictionary is used as the operand to a
- string formatting operation which yields the returned string.
- Before formatting the dictionary, a couple of preparatory steps
- are carried out. The message attribute of the record is computed
- using LogRecord.getMessage(). If the formatting string contains
- "%(asctime)", formatTime() is called to format the event time.
- If there is exception information, it is formatted using
- formatException() and appended to the message.
- '''
- record.message = record.getMessage()
- if string.find(self._fmt, '%(asctime)') >= 0:
- record.asctime = self.formatTime(record, self.datefmt)
-
- s = self._fmt % record.__dict__
- if record.exc_info:
- if not record.exc_text:
- record.exc_text = self.formatException(record.exc_info)
-
-
- if record.exc_text:
- if s[-1] != '\n':
- s = s + '\n'
-
- s = s + record.exc_text
-
- return s
-
-
- _defaultFormatter = Formatter()
-
- class BufferingFormatter:
- '''
- A formatter suitable for formatting a number of records.
- '''
-
- def __init__(self, linefmt = None):
- '''
- Optionally specify a formatter which will be used to format each
- individual record.
- '''
- if linefmt:
- self.linefmt = linefmt
- else:
- self.linefmt = _defaultFormatter
-
-
- def formatHeader(self, records):
- '''
- Return the header string for the specified records.
- '''
- return ''
-
-
- def formatFooter(self, records):
- '''
- Return the footer string for the specified records.
- '''
- return ''
-
-
- def format(self, records):
- '''
- Format the specified records and return the result as a string.
- '''
- rv = ''
- if len(records) > 0:
- rv = rv + self.formatHeader(records)
- for record in records:
- rv = rv + self.linefmt.format(record)
-
- rv = rv + self.formatFooter(records)
-
- return rv
-
-
-
- class Filter:
- '''
- Filter instances are used to perform arbitrary filtering of LogRecords.
-
- Loggers and Handlers can optionally use Filter instances to filter
- records as desired. The base filter class only allows events which are
- below a certain point in the logger hierarchy. For example, a filter
- initialized with "A.B" will allow events logged by loggers "A.B",
- "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
- initialized with the empty string, all events are passed.
- '''
-
- def __init__(self, name = ''):
- '''
- Initialize a filter.
-
- Initialize with the name of the logger which, together with its
- children, will have its events allowed through the filter. If no
- name is specified, allow every event.
- '''
- self.name = name
- self.nlen = len(name)
-
-
- def filter(self, record):
- '''
- Determine if the specified record is to be logged.
-
- Is the specified record to be logged? Returns 0 for no, nonzero for
- yes. If deemed appropriate, the record may be modified in-place.
- '''
- if self.nlen == 0:
- return 1
- elif self.name == record.name:
- return 1
- elif string.find(record.name, self.name, 0, self.nlen) != 0:
- return 0
-
- return record.name[self.nlen] == '.'
-
-
-
- class Filterer:
- '''
- A base class for loggers and handlers which allows them to share
- common code.
- '''
-
- def __init__(self):
- '''
- Initialize the list of filters to be an empty list.
- '''
- self.filters = []
-
-
- def addFilter(self, filter):
- '''
- Add the specified filter to this handler.
- '''
- if filter not in self.filters:
- self.filters.append(filter)
-
-
-
- def removeFilter(self, filter):
- '''
- Remove the specified filter from this handler.
- '''
- if filter in self.filters:
- self.filters.remove(filter)
-
-
-
- def filter(self, record):
- '''
- Determine if a record is loggable by consulting all the filters.
-
- The default is to allow the record to be logged; any filter can veto
- this and the record is then dropped. Returns a zero value if a record
- is to be dropped, else non-zero.
- '''
- rv = 1
- for f in self.filters:
- if not f.filter(record):
- rv = 0
- break
- continue
-
- return rv
-
-
- _handlers = { }
-
- class Handler(Filterer):
- """
- Handler instances dispatch logging events to specific destinations.
-
- The base handler class. Acts as a placeholder which defines the Handler
- interface. Handlers can optionally use Formatter instances to format
- records as desired. By default, no formatter is specified; in this case,
- the 'raw' message as determined by record.message is logged.
- """
-
- def __init__(self, level = NOTSET):
- '''
- Initializes the instance - basically setting the formatter to None
- and the filter list to empty.
- '''
- Filterer.__init__(self)
- self.level = level
- self.formatter = None
- _acquireLock()
-
- try:
- _handlers[self] = 1
- finally:
- _releaseLock()
-
- self.createLock()
-
-
- def createLock(self):
- '''
- Acquire a thread lock for serializing access to the underlying I/O.
- '''
- if thread:
- self.lock = thread.allocate_lock()
- else:
- self.lock = None
-
-
- def acquire(self):
- '''
- Acquire the I/O thread lock.
- '''
- if self.lock:
- self.lock.acquire()
-
-
-
- def release(self):
- '''
- Release the I/O thread lock.
- '''
- if self.lock:
- self.lock.release()
-
-
-
- def setLevel(self, level):
- '''
- Set the logging level of this handler.
- '''
- self.level = level
-
-
- def format(self, record):
- '''
- Format the specified record.
-
- If a formatter is set, use it. Otherwise, use the default formatter
- for the module.
- '''
- if self.formatter:
- fmt = self.formatter
- else:
- fmt = _defaultFormatter
- return fmt.format(record)
-
-
- def emit(self, record):
- '''
- Do whatever it takes to actually log the specified logging record.
-
- This version is intended to be implemented by subclasses and so
- raises a NotImplementedError.
- '''
- raise NotImplementedError, 'emit must be implemented by Handler subclasses'
-
-
- def handle(self, record):
- '''
- Conditionally emit the specified logging record.
-
- Emission depends on filters which may have been added to the handler.
- Wrap the actual emission of the record with acquisition/release of
- the I/O thread lock. Returns whether the filter passed the record for
- emission.
- '''
- rv = self.filter(record)
- if rv:
- self.acquire()
-
- try:
- self.emit(record)
- finally:
- self.release()
-
-
- return rv
-
-
- def setFormatter(self, fmt):
- '''
- Set the formatter for this handler.
- '''
- self.formatter = fmt
-
-
- def flush(self):
- '''
- Ensure all logging output has been flushed.
-
- This version does nothing and is intended to be implemented by
- subclasses.
- '''
- pass
-
-
- def close(self):
- '''
- Tidy up any resources used by the handler.
-
- This version does removes the handler from an internal list
- of handlers which is closed when shutdown() is called. Subclasses
- should ensure that this gets called from overridden close()
- methods.
- '''
- _acquireLock()
-
- try:
- del _handlers[self]
- finally:
- _releaseLock()
-
-
-
- def handleError(self, record):
- '''
- Handle errors which occur during an emit() call.
-
- This method should be called from handlers when an exception is
- encountered during an emit() call. If raiseExceptions is false,
- exceptions get silently ignored. This is what is mostly wanted
- for a logging system - most users will not care about errors in
- the logging system, they are more interested in application errors.
- You could, however, replace this with a custom handler if you wish.
- The record which was being processed is passed in to this method.
- '''
- if raiseExceptions:
- import traceback
- ei = sys.exc_info()
- traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
- del ei
-
-
-
-
- class StreamHandler(Handler):
- '''
- A handler class which writes logging records, appropriately formatted,
- to a stream. Note that this class does not close the stream, as
- sys.stdout or sys.stderr may be used.
- '''
-
- def __init__(self, strm = None):
- '''
- Initialize the handler.
-
- If strm is not specified, sys.stderr is used.
- '''
- Handler.__init__(self)
- if not strm:
- strm = sys.stderr
-
- self.stream = strm
- self.formatter = None
-
-
- def flush(self):
- '''
- Flushes the stream.
- '''
- self.stream.flush()
-
-
- def emit(self, record):
- '''
- Emit a record.
-
- If a formatter is specified, it is used to format the record.
- The record is then written to the stream with a trailing newline
- [N.B. this may be removed depending on feedback]. If exception
- information is present, it is formatted using
- traceback.print_exception and appended to the stream.
- '''
-
- try:
- msg = self.format(record)
- fs = '%s\n'
- if not hasattr(types, 'UnicodeType'):
- self.stream.write(fs % msg)
- else:
-
- try:
- self.stream.write(fs % msg)
- except UnicodeError:
- self.stream.write(fs % msg.encode('UTF-8'))
-
- self.flush()
- except:
- self.handleError(record)
-
-
-
-
- class FileHandler(StreamHandler):
- '''
- A handler class which writes formatted logging records to disk files.
- '''
-
- def __init__(self, filename, mode = 'a'):
- '''
- Open the specified file and use it as the stream for logging.
- '''
- StreamHandler.__init__(self, open(filename, mode))
- self.baseFilename = os.path.abspath(filename)
- self.mode = mode
-
-
- def close(self):
- '''
- Closes the stream.
- '''
- self.flush()
- self.stream.close()
- StreamHandler.close(self)
-
-
-
- class PlaceHolder:
- '''
- PlaceHolder instances are used in the Manager logger hierarchy to take
- the place of nodes for which no loggers have been defined. This class is
- intended for internal use only and not as part of the public API.
- '''
-
- def __init__(self, alogger):
- '''
- Initialize with the specified logger being a child of this placeholder.
- '''
- self.loggers = [
- alogger]
-
-
- def append(self, alogger):
- '''
- Add the specified logger as a child of this placeholder.
- '''
- if alogger not in self.loggers:
- self.loggers.append(alogger)
-
-
-
- _loggerClass = None
-
- def setLoggerClass(klass):
- '''
- Set the class to be used when instantiating a logger. The class should
- define __init__() such that only a name argument is required, and the
- __init__() should call Logger.__init__()
- '''
- global _loggerClass
- if klass != Logger:
- if not issubclass(klass, Logger):
- raise TypeError, 'logger not derived from logging.Logger: ' + klass.__name__
-
-
- _loggerClass = klass
-
-
- def getLoggerClass():
- '''
- Return the class to be used when instantiating a logger.
- '''
- return _loggerClass
-
-
- class Manager:
- '''
- There is [under normal circumstances] just one Manager instance, which
- holds the hierarchy of loggers.
- '''
-
- def __init__(self, rootnode):
- '''
- Initialize the manager with the root node of the logger hierarchy.
- '''
- self.root = rootnode
- self.disable = 0
- self.emittedNoHandlerWarning = 0
- self.loggerDict = { }
-
-
- def getLogger(self, name):
- '''
- Get a logger with the specified name (channel name), creating it
- if it doesn\'t yet exist. This name is a dot-separated hierarchical
- name, such as "a", "a.b", "a.b.c" or similar.
-
- If a PlaceHolder existed for the specified name [i.e. the logger
- didn\'t exist but a child of it did], replace it with the created
- logger and fix up the parent/child references which pointed to the
- placeholder to now point to the logger.
- '''
- rv = None
- _acquireLock()
-
- try:
- if self.loggerDict.has_key(name):
- rv = self.loggerDict[name]
- if isinstance(rv, PlaceHolder):
- ph = rv
- rv = _loggerClass(name)
- rv.manager = self
- self.loggerDict[name] = rv
- self._fixupChildren(ph, rv)
- self._fixupParents(rv)
-
- else:
- rv = _loggerClass(name)
- rv.manager = self
- self.loggerDict[name] = rv
- self._fixupParents(rv)
- finally:
- _releaseLock()
-
- return rv
-
-
- def _fixupParents(self, alogger):
- '''
- Ensure that there are either loggers or placeholders all the way
- from the specified logger to the root of the logger hierarchy.
- '''
- name = alogger.name
- i = string.rfind(name, '.')
- rv = None
- while i > 0 and not rv:
- substr = name[:i]
- if not self.loggerDict.has_key(substr):
- self.loggerDict[substr] = PlaceHolder(alogger)
- else:
- obj = self.loggerDict[substr]
- if isinstance(obj, Logger):
- rv = obj
- elif not isinstance(obj, PlaceHolder):
- raise AssertionError
- obj.append(alogger)
- i = string.rfind(name, '.', 0, i - 1)
- if not rv:
- rv = self.root
-
- alogger.parent = rv
-
-
- def _fixupChildren(self, ph, alogger):
- '''
- Ensure that children of the placeholder ph are connected to the
- specified logger.
- '''
- for c in ph.loggers:
- if string.find(c.parent.name, alogger.name) != 0:
- alogger.parent = c.parent
- c.parent = alogger
- continue
-
-
-
-
- class Logger(Filterer):
- '''
- Instances of the Logger class represent a single logging channel. A
- "logging channel" indicates an area of an application. Exactly how an
- "area" is defined is up to the application developer. Since an
- application can have any number of areas, logging channels are identified
- by a unique string. Application areas can be nested (e.g. an area
- of "input processing" might include sub-areas "read CSV files", "read
- XLS files" and "read Gnumeric files"). To cater for this natural nesting,
- channel names are organized into a namespace hierarchy where levels are
- separated by periods, much like the Java or Python package namespace. So
- in the instance given above, channel names might be "input" for the upper
- level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
- There is no arbitrary limit to the depth of nesting.
- '''
-
- def __init__(self, name, level = NOTSET):
- '''
- Initialize the logger with a name and an optional level.
- '''
- Filterer.__init__(self)
- self.name = name
- self.level = level
- self.parent = None
- self.propagate = 1
- self.handlers = []
- self.disabled = 0
-
-
- def setLevel(self, level):
- '''
- Set the logging level of this logger.
- '''
- self.level = level
-
-
- def debug(self, msg, *args, **kwargs):
- '''
- Log \'msg % args\' with severity \'DEBUG\'.
-
- To pass exception information, use the keyword argument exc_info with
- a true value, e.g.
-
- logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
- '''
- if self.manager.disable >= DEBUG:
- return None
-
- if DEBUG >= self.getEffectiveLevel():
- apply(self._log, (DEBUG, msg, args), kwargs)
-
-
-
- def info(self, msg, *args, **kwargs):
- '''
- Log \'msg % args\' with severity \'INFO\'.
-
- To pass exception information, use the keyword argument exc_info with
- a true value, e.g.
-
- logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
- '''
- if self.manager.disable >= INFO:
- return None
-
- if INFO >= self.getEffectiveLevel():
- apply(self._log, (INFO, msg, args), kwargs)
-
-
-
- def warning(self, msg, *args, **kwargs):
- '''
- Log \'msg % args\' with severity \'WARNING\'.
-
- To pass exception information, use the keyword argument exc_info with
- a true value, e.g.
-
- logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
- '''
- if self.manager.disable >= WARNING:
- return None
-
- if self.isEnabledFor(WARNING):
- apply(self._log, (WARNING, msg, args), kwargs)
-
-
- warn = warning
-
- def error(self, msg, *args, **kwargs):
- '''
- Log \'msg % args\' with severity \'ERROR\'.
-
- To pass exception information, use the keyword argument exc_info with
- a true value, e.g.
-
- logger.error("Houston, we have a %s", "major problem", exc_info=1)
- '''
- if self.manager.disable >= ERROR:
- return None
-
- if self.isEnabledFor(ERROR):
- apply(self._log, (ERROR, msg, args), kwargs)
-
-
-
- def exception(self, msg, *args):
- '''
- Convenience method for logging an ERROR with exception information.
- '''
- apply(self.error, (msg,) + args, {
- 'exc_info': 1 })
-
-
- def critical(self, msg, *args, **kwargs):
- '''
- Log \'msg % args\' with severity \'CRITICAL\'.
-
- To pass exception information, use the keyword argument exc_info with
- a true value, e.g.
-
- logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
- '''
- if self.manager.disable >= CRITICAL:
- return None
-
- if CRITICAL >= self.getEffectiveLevel():
- apply(self._log, (CRITICAL, msg, args), kwargs)
-
-
- fatal = critical
-
- def log(self, level, msg, *args, **kwargs):
- '''
- Log \'msg % args\' with the integer severity \'level\'.
-
- To pass exception information, use the keyword argument exc_info with
- a true value, e.g.
-
- logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
- '''
- if type(level) != types.IntType:
- if raiseExceptions:
- raise TypeError, 'level must be an integer'
- else:
- return None
-
- if self.manager.disable >= level:
- return None
-
- if self.isEnabledFor(level):
- apply(self._log, (level, msg, args), kwargs)
-
-
-
- def findCaller(self):
- '''
- Find the stack frame of the caller so that we can note the source
- file name and line number.
- '''
- f = sys._getframe(1)
- while None:
- co = f.f_code
- filename = os.path.normcase(co.co_filename)
- if filename == _srcfile:
- f = f.f_back
- continue
-
- return (filename, f.f_lineno)
-
-
- def makeRecord(self, name, level, fn, lno, msg, args, exc_info):
- '''
- A factory method which can be overridden in subclasses to create
- specialized LogRecords.
- '''
- return LogRecord(name, level, fn, lno, msg, args, exc_info)
-
-
- def _log(self, level, msg, args, exc_info = None):
- '''
- Low-level logging routine which creates a LogRecord and then calls
- all the handlers of this logger to handle the record.
- '''
- if _srcfile:
- (fn, lno) = self.findCaller()
- else:
- (fn, lno) = ('<unknown file>', 0)
- if exc_info:
- if type(exc_info) != types.TupleType:
- exc_info = sys.exc_info()
-
-
- record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info)
- self.handle(record)
-
-
- def handle(self, record):
- '''
- Call the handlers for the specified record.
-
- This method is used for unpickled records received from a socket, as
- well as those created locally. Logger-level filtering is applied.
- '''
- if not (self.disabled) and self.filter(record):
- self.callHandlers(record)
-
-
-
- def addHandler(self, hdlr):
- '''
- Add the specified handler to this logger.
- '''
- if hdlr not in self.handlers:
- self.handlers.append(hdlr)
-
-
-
- def removeHandler(self, hdlr):
- '''
- Remove the specified handler from this logger.
- '''
- if hdlr in self.handlers:
- self.handlers.remove(hdlr)
-
-
-
- def callHandlers(self, record):
- '''
- Pass a record to all relevant handlers.
-
- Loop through all handlers for this logger and its parents in the
- logger hierarchy. If no handler was found, output a one-off error
- message to sys.stderr. Stop searching up the hierarchy whenever a
- logger with the "propagate" attribute set to zero is found - that
- will be the last logger whose handlers are called.
- '''
- c = self
- found = 0
- while c:
- for hdlr in c.handlers:
- found = found + 1
- if record.levelno >= hdlr.level:
- hdlr.handle(record)
- continue
-
- if not c.propagate:
- c = None
- continue
- c = c.parent
- if found == 0 and not (self.manager.emittedNoHandlerWarning):
- sys.stderr.write('No handlers could be found for logger "%s"\n' % self.name)
- self.manager.emittedNoHandlerWarning = 1
-
-
-
- def getEffectiveLevel(self):
- '''
- Get the effective level for this logger.
-
- Loop through this logger and its parents in the logger hierarchy,
- looking for a non-zero logging level. Return the first one found.
- '''
- logger = self
- while logger:
- if logger.level:
- return logger.level
-
- logger = logger.parent
- return NOTSET
-
-
- def isEnabledFor(self, level):
- """
- Is this logger enabled for level 'level'?
- """
- if self.manager.disable >= level:
- return 0
-
- return level >= self.getEffectiveLevel()
-
-
-
- class RootLogger(Logger):
- '''
- A root logger is not that different to any other logger, except that
- it must have a logging level and there is only one instance of it in
- the hierarchy.
- '''
-
- def __init__(self, level):
- '''
- Initialize the logger with the name "root".
- '''
- Logger.__init__(self, 'root', level)
-
-
- _loggerClass = Logger
- root = RootLogger(WARNING)
- Logger.root = root
- Logger.manager = Manager(Logger.root)
- BASIC_FORMAT = '%(levelname)s:%(name)s:%(message)s'
-
- def basicConfig(**kwargs):
- '''
- Do basic configuration for the logging system.
-
- This function does nothing if the root logger already has handlers
- configured. It is a convenience method intended for use by simple scripts
- to do one-shot configuration of the logging package.
-
- The default behaviour is to create a StreamHandler which writes to
- sys.stderr, set a formatter using the BASIC_FORMAT format string, and
- add the handler to the root logger.
-
- A number of optional keyword arguments may be specified, which can alter
- the default behaviour.
-
- filename Specifies that a FileHandler be created, using the specified
- filename, rather than a StreamHandler.
- filemode Specifies the mode to open the file, if filename is specified
- (if filemode is unspecified, it defaults to "a").
- format Use the specified format string for the handler.
- datefmt Use the specified date/time format.
- level Set the root logger level to the specified level.
- stream Use the specified stream to initialize the StreamHandler. Note
- that this argument is incompatible with \'filename\' - if both
- are present, \'stream\' is ignored.
-
- Note that you could specify a stream created using open(filename, mode)
- rather than passing the filename and mode in. However, it should be
- remembered that StreamHandler does not close its stream (since it may be
- using sys.stdout or sys.stderr), whereas FileHandler closes its stream
- when the handler is closed.
- '''
- if len(root.handlers) == 0:
- filename = kwargs.get('filename')
- if filename:
- mode = kwargs.get('filemode', 'a')
- hdlr = FileHandler(filename, mode)
- else:
- stream = kwargs.get('stream')
- hdlr = StreamHandler(stream)
- fs = kwargs.get('format', BASIC_FORMAT)
- dfs = kwargs.get('datefmt', None)
- fmt = Formatter(fs, dfs)
- hdlr.setFormatter(fmt)
- root.addHandler(hdlr)
- level = kwargs.get('level')
- if level:
- root.setLevel(level)
-
-
-
-
- def getLogger(name = None):
- '''
- Return a logger with the specified name, creating it if necessary.
-
- If no name is specified, return the root logger.
- '''
- if name:
- return Logger.manager.getLogger(name)
- else:
- return root
-
-
- def critical(msg, *args, **kwargs):
- """
- Log a message with severity 'CRITICAL' on the root logger.
- """
- if len(root.handlers) == 0:
- basicConfig()
-
- apply(root.critical, (msg,) + args, kwargs)
-
- fatal = critical
-
- def error(msg, *args, **kwargs):
- """
- Log a message with severity 'ERROR' on the root logger.
- """
- if len(root.handlers) == 0:
- basicConfig()
-
- apply(root.error, (msg,) + args, kwargs)
-
-
- def exception(msg, *args):
- """
- Log a message with severity 'ERROR' on the root logger,
- with exception information.
- """
- apply(error, (msg,) + args, {
- 'exc_info': 1 })
-
-
- def warning(msg, *args, **kwargs):
- """
- Log a message with severity 'WARNING' on the root logger.
- """
- if len(root.handlers) == 0:
- basicConfig()
-
- apply(root.warning, (msg,) + args, kwargs)
-
- warn = warning
-
- def info(msg, *args, **kwargs):
- """
- Log a message with severity 'INFO' on the root logger.
- """
- if len(root.handlers) == 0:
- basicConfig()
-
- apply(root.info, (msg,) + args, kwargs)
-
-
- def debug(msg, *args, **kwargs):
- """
- Log a message with severity 'DEBUG' on the root logger.
- """
- if len(root.handlers) == 0:
- basicConfig()
-
- apply(root.debug, (msg,) + args, kwargs)
-
-
- def log(level, msg, *args, **kwargs):
- """
- Log 'msg % args' with the integer severity 'level' on the root logger.
- """
- if len(root.handlers) == 0:
- basicConfig()
-
- apply(root.log, (level, msg) + args, kwargs)
-
-
- def disable(level):
- """
- Disable all logging calls less severe than 'level'.
- """
- root.manager.disable = level
-
-
- def shutdown():
- '''
- Perform any cleanup actions in the logging system (e.g. flushing
- buffers).
-
- Should be called at application exit.
- '''
- for h in _handlers.keys():
-
- try:
- h.flush()
- h.close()
- continue
- continue
-
-
-
-
- try:
- import atexit
- atexit.register(shutdown)
- except ImportError:
-
- def exithook(status, old_exit = sys.exit):
-
- try:
- shutdown()
- finally:
- old_exit(status)
-
-
- sys.exit = exithook
-
-