Added LoggerAdapter class, changed copyright dates, made check for extra parameter...
[python.git] / Lib / logging / __init__.py
blob2cb2bc906dba1da96532d0090a212aabc2491a70
1 # Copyright 2001-2008 by Vinay Sajip. All Rights Reserved.
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.
17 """
18 Logging package for Python. Based on PEP 282 and comments thereto in
19 comp.lang.python, and influenced by Apache's log4j system.
21 Should work under Python versions >= 1.5.2, except that source line
22 information is not available unless 'sys._getframe()' is.
24 Copyright (C) 2001-2008 Vinay Sajip. All Rights Reserved.
26 To use, simply 'import logging' and log away!
27 """
29 import sys, os, types, time, string, cStringIO, traceback
31 try:
32 import codecs
33 except ImportError:
34 codecs = None
36 try:
37 import thread
38 import threading
39 except ImportError:
40 thread = None
42 __author__ = "Vinay Sajip <vinay_sajip@red-dove.com>"
43 __status__ = "production"
44 __version__ = "0.5.0.4"
45 __date__ = "18 January 2008"
47 #---------------------------------------------------------------------------
48 # Miscellaneous module data
49 #---------------------------------------------------------------------------
52 # _srcfile is used when walking the stack to check when we've got the first
53 # caller stack frame.
55 if hasattr(sys, 'frozen'): #support for py2exe
56 _srcfile = "logging%s__init__%s" % (os.sep, __file__[-4:])
57 elif string.lower(__file__[-4:]) in ['.pyc', '.pyo']:
58 _srcfile = __file__[:-4] + '.py'
59 else:
60 _srcfile = __file__
61 _srcfile = os.path.normcase(_srcfile)
63 # next bit filched from 1.5.2's inspect.py
64 def currentframe():
65 """Return the frame object for the caller's stack frame."""
66 try:
67 raise Exception
68 except:
69 return sys.exc_traceback.tb_frame.f_back
71 if hasattr(sys, '_getframe'): currentframe = lambda: sys._getframe(3)
72 # done filching
74 # _srcfile is only used in conjunction with sys._getframe().
75 # To provide compatibility with older versions of Python, set _srcfile
76 # to None if _getframe() is not available; this value will prevent
77 # findCaller() from being called.
78 #if not hasattr(sys, "_getframe"):
79 # _srcfile = None
82 #_startTime is used as the base when calculating the relative time of events
84 _startTime = time.time()
87 #raiseExceptions is used to see if exceptions during handling should be
88 #propagated
90 raiseExceptions = 1
93 # If you don't want threading information in the log, set this to zero
95 logThreads = 1
98 # If you don't want process information in the log, set this to zero
100 logProcesses = 1
102 #---------------------------------------------------------------------------
103 # Level related stuff
104 #---------------------------------------------------------------------------
106 # Default levels and level names, these can be replaced with any positive set
107 # of values having corresponding names. There is a pseudo-level, NOTSET, which
108 # is only really there as a lower limit for user-defined levels. Handlers and
109 # loggers are initialized with NOTSET so that they will log all messages, even
110 # at user-defined levels.
113 CRITICAL = 50
114 FATAL = CRITICAL
115 ERROR = 40
116 WARNING = 30
117 WARN = WARNING
118 INFO = 20
119 DEBUG = 10
120 NOTSET = 0
122 _levelNames = {
123 CRITICAL : 'CRITICAL',
124 ERROR : 'ERROR',
125 WARNING : 'WARNING',
126 INFO : 'INFO',
127 DEBUG : 'DEBUG',
128 NOTSET : 'NOTSET',
129 'CRITICAL' : CRITICAL,
130 'ERROR' : ERROR,
131 'WARN' : WARNING,
132 'WARNING' : WARNING,
133 'INFO' : INFO,
134 'DEBUG' : DEBUG,
135 'NOTSET' : NOTSET,
138 def getLevelName(level):
140 Return the textual representation of logging level 'level'.
142 If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
143 INFO, DEBUG) then you get the corresponding string. If you have
144 associated levels with names using addLevelName then the name you have
145 associated with 'level' is returned.
147 If a numeric value corresponding to one of the defined levels is passed
148 in, the corresponding string representation is returned.
150 Otherwise, the string "Level %s" % level is returned.
152 return _levelNames.get(level, ("Level %s" % level))
154 def addLevelName(level, levelName):
156 Associate 'levelName' with 'level'.
158 This is used when converting levels to text during message formatting.
160 _acquireLock()
161 try: #unlikely to cause an exception, but you never know...
162 _levelNames[level] = levelName
163 _levelNames[levelName] = level
164 finally:
165 _releaseLock()
167 #---------------------------------------------------------------------------
168 # Thread-related stuff
169 #---------------------------------------------------------------------------
172 #_lock is used to serialize access to shared data structures in this module.
173 #This needs to be an RLock because fileConfig() creates Handlers and so
174 #might arbitrary user threads. Since Handler.__init__() updates the shared
175 #dictionary _handlers, it needs to acquire the lock. But if configuring,
176 #the lock would already have been acquired - so we need an RLock.
177 #The same argument applies to Loggers and Manager.loggerDict.
179 _lock = None
181 def _acquireLock():
183 Acquire the module-level lock for serializing access to shared data.
185 This should be released with _releaseLock().
187 global _lock
188 if (not _lock) and thread:
189 _lock = threading.RLock()
190 if _lock:
191 _lock.acquire()
193 def _releaseLock():
195 Release the module-level lock acquired by calling _acquireLock().
197 if _lock:
198 _lock.release()
200 #---------------------------------------------------------------------------
201 # The logging record
202 #---------------------------------------------------------------------------
204 class LogRecord:
206 A LogRecord instance represents an event being logged.
208 LogRecord instances are created every time something is logged. They
209 contain all the information pertinent to the event being logged. The
210 main information passed in is in msg and args, which are combined
211 using str(msg) % args to create the message field of the record. The
212 record also includes information such as when the record was created,
213 the source line where the logging call was made, and any exception
214 information to be logged.
216 def __init__(self, name, level, pathname, lineno,
217 msg, args, exc_info, func=None):
219 Initialize a logging record with interesting information.
221 ct = time.time()
222 self.name = name
223 self.msg = msg
225 # The following statement allows passing of a dictionary as a sole
226 # argument, so that you can do something like
227 # logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2})
228 # Suggested by Stefan Behnel.
229 # Note that without the test for args[0], we get a problem because
230 # during formatting, we test to see if the arg is present using
231 # 'if self.args:'. If the event being logged is e.g. 'Value is %d'
232 # and if the passed arg fails 'if self.args:' then no formatting
233 # is done. For example, logger.warn('Value is %d', 0) would log
234 # 'Value is %d' instead of 'Value is 0'.
235 # For the use case of passing a dictionary, this should not be a
236 # problem.
237 if args and len(args) == 1 and (
238 type(args[0]) == types.DictType
239 ) and args[0]:
240 args = args[0]
241 self.args = args
242 self.levelname = getLevelName(level)
243 self.levelno = level
244 self.pathname = pathname
245 try:
246 self.filename = os.path.basename(pathname)
247 self.module = os.path.splitext(self.filename)[0]
248 except (TypeError, ValueError, AttributeError):
249 self.filename = pathname
250 self.module = "Unknown module"
251 self.exc_info = exc_info
252 self.exc_text = None # used to cache the traceback text
253 self.lineno = lineno
254 self.funcName = func
255 self.created = ct
256 self.msecs = (ct - long(ct)) * 1000
257 self.relativeCreated = (self.created - _startTime) * 1000
258 if logThreads and thread:
259 self.thread = thread.get_ident()
260 self.threadName = threading.currentThread().getName()
261 else:
262 self.thread = None
263 self.threadName = None
264 if logProcesses and hasattr(os, 'getpid'):
265 self.process = os.getpid()
266 else:
267 self.process = None
269 def __str__(self):
270 return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
271 self.pathname, self.lineno, self.msg)
273 def getMessage(self):
275 Return the message for this LogRecord.
277 Return the message for this LogRecord after merging any user-supplied
278 arguments with the message.
280 if not hasattr(types, "UnicodeType"): #if no unicode support...
281 msg = str(self.msg)
282 else:
283 msg = self.msg
284 if type(msg) not in (types.UnicodeType, types.StringType):
285 try:
286 msg = str(self.msg)
287 except UnicodeError:
288 msg = self.msg #Defer encoding till later
289 if self.args:
290 msg = msg % self.args
291 return msg
293 def makeLogRecord(dict):
295 Make a LogRecord whose attributes are defined by the specified dictionary,
296 This function is useful for converting a logging event received over
297 a socket connection (which is sent as a dictionary) into a LogRecord
298 instance.
300 rv = LogRecord(None, None, "", 0, "", (), None, None)
301 rv.__dict__.update(dict)
302 return rv
304 #---------------------------------------------------------------------------
305 # Formatter classes and functions
306 #---------------------------------------------------------------------------
308 class Formatter:
310 Formatter instances are used to convert a LogRecord to text.
312 Formatters need to know how a LogRecord is constructed. They are
313 responsible for converting a LogRecord to (usually) a string which can
314 be interpreted by either a human or an external system. The base Formatter
315 allows a formatting string to be specified. If none is supplied, the
316 default value of "%s(message)\\n" is used.
318 The Formatter can be initialized with a format string which makes use of
319 knowledge of the LogRecord attributes - e.g. the default value mentioned
320 above makes use of the fact that the user's message and arguments are pre-
321 formatted into a LogRecord's message attribute. Currently, the useful
322 attributes in a LogRecord are described by:
324 %(name)s Name of the logger (logging channel)
325 %(levelno)s Numeric logging level for the message (DEBUG, INFO,
326 WARNING, ERROR, CRITICAL)
327 %(levelname)s Text logging level for the message ("DEBUG", "INFO",
328 "WARNING", "ERROR", "CRITICAL")
329 %(pathname)s Full pathname of the source file where the logging
330 call was issued (if available)
331 %(filename)s Filename portion of pathname
332 %(module)s Module (name portion of filename)
333 %(lineno)d Source line number where the logging call was issued
334 (if available)
335 %(funcName)s Function name
336 %(created)f Time when the LogRecord was created (time.time()
337 return value)
338 %(asctime)s Textual time when the LogRecord was created
339 %(msecs)d Millisecond portion of the creation time
340 %(relativeCreated)d Time in milliseconds when the LogRecord was created,
341 relative to the time the logging module was loaded
342 (typically at application startup time)
343 %(thread)d Thread ID (if available)
344 %(threadName)s Thread name (if available)
345 %(process)d Process ID (if available)
346 %(message)s The result of record.getMessage(), computed just as
347 the record is emitted
350 converter = time.localtime
352 def __init__(self, fmt=None, datefmt=None):
354 Initialize the formatter with specified format strings.
356 Initialize the formatter either with the specified format string, or a
357 default as described above. Allow for specialized date formatting with
358 the optional datefmt argument (if omitted, you get the ISO8601 format).
360 if fmt:
361 self._fmt = fmt
362 else:
363 self._fmt = "%(message)s"
364 self.datefmt = datefmt
366 def formatTime(self, record, datefmt=None):
368 Return the creation time of the specified LogRecord as formatted text.
370 This method should be called from format() by a formatter which
371 wants to make use of a formatted time. This method can be overridden
372 in formatters to provide for any specific requirement, but the
373 basic behaviour is as follows: if datefmt (a string) is specified,
374 it is used with time.strftime() to format the creation time of the
375 record. Otherwise, the ISO8601 format is used. The resulting
376 string is returned. This function uses a user-configurable function
377 to convert the creation time to a tuple. By default, time.localtime()
378 is used; to change this for a particular formatter instance, set the
379 'converter' attribute to a function with the same signature as
380 time.localtime() or time.gmtime(). To change it for all formatters,
381 for example if you want all logging times to be shown in GMT,
382 set the 'converter' attribute in the Formatter class.
384 ct = self.converter(record.created)
385 if datefmt:
386 s = time.strftime(datefmt, ct)
387 else:
388 t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
389 s = "%s,%03d" % (t, record.msecs)
390 return s
392 def formatException(self, ei):
394 Format and return the specified exception information as a string.
396 This default implementation just uses
397 traceback.print_exception()
399 sio = cStringIO.StringIO()
400 traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
401 s = sio.getvalue()
402 sio.close()
403 if s[-1:] == "\n":
404 s = s[:-1]
405 return s
407 def format(self, record):
409 Format the specified record as text.
411 The record's attribute dictionary is used as the operand to a
412 string formatting operation which yields the returned string.
413 Before formatting the dictionary, a couple of preparatory steps
414 are carried out. The message attribute of the record is computed
415 using LogRecord.getMessage(). If the formatting string contains
416 "%(asctime)", formatTime() is called to format the event time.
417 If there is exception information, it is formatted using
418 formatException() and appended to the message.
420 record.message = record.getMessage()
421 if string.find(self._fmt,"%(asctime)") >= 0:
422 record.asctime = self.formatTime(record, self.datefmt)
423 s = self._fmt % record.__dict__
424 if record.exc_info:
425 # Cache the traceback text to avoid converting it multiple times
426 # (it's constant anyway)
427 if not record.exc_text:
428 record.exc_text = self.formatException(record.exc_info)
429 if record.exc_text:
430 if s[-1:] != "\n":
431 s = s + "\n"
432 s = s + record.exc_text
433 return s
436 # The default formatter to use when no other is specified
438 _defaultFormatter = Formatter()
440 class BufferingFormatter:
442 A formatter suitable for formatting a number of records.
444 def __init__(self, linefmt=None):
446 Optionally specify a formatter which will be used to format each
447 individual record.
449 if linefmt:
450 self.linefmt = linefmt
451 else:
452 self.linefmt = _defaultFormatter
454 def formatHeader(self, records):
456 Return the header string for the specified records.
458 return ""
460 def formatFooter(self, records):
462 Return the footer string for the specified records.
464 return ""
466 def format(self, records):
468 Format the specified records and return the result as a string.
470 rv = ""
471 if len(records) > 0:
472 rv = rv + self.formatHeader(records)
473 for record in records:
474 rv = rv + self.linefmt.format(record)
475 rv = rv + self.formatFooter(records)
476 return rv
478 #---------------------------------------------------------------------------
479 # Filter classes and functions
480 #---------------------------------------------------------------------------
482 class Filter:
484 Filter instances are used to perform arbitrary filtering of LogRecords.
486 Loggers and Handlers can optionally use Filter instances to filter
487 records as desired. The base filter class only allows events which are
488 below a certain point in the logger hierarchy. For example, a filter
489 initialized with "A.B" will allow events logged by loggers "A.B",
490 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
491 initialized with the empty string, all events are passed.
493 def __init__(self, name=''):
495 Initialize a filter.
497 Initialize with the name of the logger which, together with its
498 children, will have its events allowed through the filter. If no
499 name is specified, allow every event.
501 self.name = name
502 self.nlen = len(name)
504 def filter(self, record):
506 Determine if the specified record is to be logged.
508 Is the specified record to be logged? Returns 0 for no, nonzero for
509 yes. If deemed appropriate, the record may be modified in-place.
511 if self.nlen == 0:
512 return 1
513 elif self.name == record.name:
514 return 1
515 elif string.find(record.name, self.name, 0, self.nlen) != 0:
516 return 0
517 return (record.name[self.nlen] == ".")
519 class Filterer:
521 A base class for loggers and handlers which allows them to share
522 common code.
524 def __init__(self):
526 Initialize the list of filters to be an empty list.
528 self.filters = []
530 def addFilter(self, filter):
532 Add the specified filter to this handler.
534 if not (filter in self.filters):
535 self.filters.append(filter)
537 def removeFilter(self, filter):
539 Remove the specified filter from this handler.
541 if filter in self.filters:
542 self.filters.remove(filter)
544 def filter(self, record):
546 Determine if a record is loggable by consulting all the filters.
548 The default is to allow the record to be logged; any filter can veto
549 this and the record is then dropped. Returns a zero value if a record
550 is to be dropped, else non-zero.
552 rv = 1
553 for f in self.filters:
554 if not f.filter(record):
555 rv = 0
556 break
557 return rv
559 #---------------------------------------------------------------------------
560 # Handler classes and functions
561 #---------------------------------------------------------------------------
563 _handlers = {} #repository of handlers (for flushing when shutdown called)
564 _handlerList = [] # added to allow handlers to be removed in reverse of order initialized
566 class Handler(Filterer):
568 Handler instances dispatch logging events to specific destinations.
570 The base handler class. Acts as a placeholder which defines the Handler
571 interface. Handlers can optionally use Formatter instances to format
572 records as desired. By default, no formatter is specified; in this case,
573 the 'raw' message as determined by record.message is logged.
575 def __init__(self, level=NOTSET):
577 Initializes the instance - basically setting the formatter to None
578 and the filter list to empty.
580 Filterer.__init__(self)
581 self.level = level
582 self.formatter = None
583 #get the module data lock, as we're updating a shared structure.
584 _acquireLock()
585 try: #unlikely to raise an exception, but you never know...
586 _handlers[self] = 1
587 _handlerList.insert(0, self)
588 finally:
589 _releaseLock()
590 self.createLock()
592 def createLock(self):
594 Acquire a thread lock for serializing access to the underlying I/O.
596 if thread:
597 self.lock = threading.RLock()
598 else:
599 self.lock = None
601 def acquire(self):
603 Acquire the I/O thread lock.
605 if self.lock:
606 self.lock.acquire()
608 def release(self):
610 Release the I/O thread lock.
612 if self.lock:
613 self.lock.release()
615 def setLevel(self, level):
617 Set the logging level of this handler.
619 self.level = level
621 def format(self, record):
623 Format the specified record.
625 If a formatter is set, use it. Otherwise, use the default formatter
626 for the module.
628 if self.formatter:
629 fmt = self.formatter
630 else:
631 fmt = _defaultFormatter
632 return fmt.format(record)
634 def emit(self, record):
636 Do whatever it takes to actually log the specified logging record.
638 This version is intended to be implemented by subclasses and so
639 raises a NotImplementedError.
641 raise NotImplementedError, 'emit must be implemented '\
642 'by Handler subclasses'
644 def handle(self, record):
646 Conditionally emit the specified logging record.
648 Emission depends on filters which may have been added to the handler.
649 Wrap the actual emission of the record with acquisition/release of
650 the I/O thread lock. Returns whether the filter passed the record for
651 emission.
653 rv = self.filter(record)
654 if rv:
655 self.acquire()
656 try:
657 self.emit(record)
658 finally:
659 self.release()
660 return rv
662 def setFormatter(self, fmt):
664 Set the formatter for this handler.
666 self.formatter = fmt
668 def flush(self):
670 Ensure all logging output has been flushed.
672 This version does nothing and is intended to be implemented by
673 subclasses.
675 pass
677 def close(self):
679 Tidy up any resources used by the handler.
681 This version does removes the handler from an internal list
682 of handlers which is closed when shutdown() is called. Subclasses
683 should ensure that this gets called from overridden close()
684 methods.
686 #get the module data lock, as we're updating a shared structure.
687 _acquireLock()
688 try: #unlikely to raise an exception, but you never know...
689 del _handlers[self]
690 _handlerList.remove(self)
691 finally:
692 _releaseLock()
694 def handleError(self, record):
696 Handle errors which occur during an emit() call.
698 This method should be called from handlers when an exception is
699 encountered during an emit() call. If raiseExceptions is false,
700 exceptions get silently ignored. This is what is mostly wanted
701 for a logging system - most users will not care about errors in
702 the logging system, they are more interested in application errors.
703 You could, however, replace this with a custom handler if you wish.
704 The record which was being processed is passed in to this method.
706 if raiseExceptions:
707 ei = sys.exc_info()
708 traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
709 del ei
711 class StreamHandler(Handler):
713 A handler class which writes logging records, appropriately formatted,
714 to a stream. Note that this class does not close the stream, as
715 sys.stdout or sys.stderr may be used.
717 def __init__(self, strm=None):
719 Initialize the handler.
721 If strm is not specified, sys.stderr is used.
723 Handler.__init__(self)
724 if strm is None:
725 strm = sys.stderr
726 self.stream = strm
727 self.formatter = None
729 def flush(self):
731 Flushes the stream.
733 if self.stream:
734 self.stream.flush()
736 def emit(self, record):
738 Emit a record.
740 If a formatter is specified, it is used to format the record.
741 The record is then written to the stream with a trailing newline
742 [N.B. this may be removed depending on feedback]. If exception
743 information is present, it is formatted using
744 traceback.print_exception and appended to the stream.
746 try:
747 msg = self.format(record)
748 fs = "%s\n"
749 if not hasattr(types, "UnicodeType"): #if no unicode support...
750 self.stream.write(fs % msg)
751 else:
752 try:
753 self.stream.write(fs % msg)
754 except UnicodeError:
755 self.stream.write(fs % msg.encode("UTF-8"))
756 self.flush()
757 except (KeyboardInterrupt, SystemExit):
758 raise
759 except:
760 self.handleError(record)
762 class FileHandler(StreamHandler):
764 A handler class which writes formatted logging records to disk files.
766 def __init__(self, filename, mode='a', encoding=None):
768 Open the specified file and use it as the stream for logging.
770 #keep the absolute path, otherwise derived classes which use this
771 #may come a cropper when the current directory changes
772 if codecs is None:
773 encoding = None
774 self.baseFilename = os.path.abspath(filename)
775 self.mode = mode
776 self.encoding = encoding
777 stream = self._open()
778 StreamHandler.__init__(self, stream)
780 def close(self):
782 Closes the stream.
784 if self.stream:
785 self.flush()
786 self.stream.close()
787 StreamHandler.close(self)
788 self.stream = None
790 def _open(self):
792 Open the current base file with the (original) mode and encoding.
793 Return the resulting stream.
795 if self.encoding is None:
796 stream = open(self.baseFilename, self.mode)
797 else:
798 stream = codecs.open(self.baseFilename, self.mode, self.encoding)
799 return stream
801 #---------------------------------------------------------------------------
802 # Manager classes and functions
803 #---------------------------------------------------------------------------
805 class PlaceHolder:
807 PlaceHolder instances are used in the Manager logger hierarchy to take
808 the place of nodes for which no loggers have been defined. This class is
809 intended for internal use only and not as part of the public API.
811 def __init__(self, alogger):
813 Initialize with the specified logger being a child of this placeholder.
815 #self.loggers = [alogger]
816 self.loggerMap = { alogger : None }
818 def append(self, alogger):
820 Add the specified logger as a child of this placeholder.
822 #if alogger not in self.loggers:
823 if not self.loggerMap.has_key(alogger):
824 #self.loggers.append(alogger)
825 self.loggerMap[alogger] = None
828 # Determine which class to use when instantiating loggers.
830 _loggerClass = None
832 def setLoggerClass(klass):
834 Set the class to be used when instantiating a logger. The class should
835 define __init__() such that only a name argument is required, and the
836 __init__() should call Logger.__init__()
838 if klass != Logger:
839 if not issubclass(klass, Logger):
840 raise TypeError, "logger not derived from logging.Logger: " + \
841 klass.__name__
842 global _loggerClass
843 _loggerClass = klass
845 def getLoggerClass():
847 Return the class to be used when instantiating a logger.
850 return _loggerClass
852 class Manager:
854 There is [under normal circumstances] just one Manager instance, which
855 holds the hierarchy of loggers.
857 def __init__(self, rootnode):
859 Initialize the manager with the root node of the logger hierarchy.
861 self.root = rootnode
862 self.disable = 0
863 self.emittedNoHandlerWarning = 0
864 self.loggerDict = {}
866 def getLogger(self, name):
868 Get a logger with the specified name (channel name), creating it
869 if it doesn't yet exist. This name is a dot-separated hierarchical
870 name, such as "a", "a.b", "a.b.c" or similar.
872 If a PlaceHolder existed for the specified name [i.e. the logger
873 didn't exist but a child of it did], replace it with the created
874 logger and fix up the parent/child references which pointed to the
875 placeholder to now point to the logger.
877 rv = None
878 _acquireLock()
879 try:
880 if self.loggerDict.has_key(name):
881 rv = self.loggerDict[name]
882 if isinstance(rv, PlaceHolder):
883 ph = rv
884 rv = _loggerClass(name)
885 rv.manager = self
886 self.loggerDict[name] = rv
887 self._fixupChildren(ph, rv)
888 self._fixupParents(rv)
889 else:
890 rv = _loggerClass(name)
891 rv.manager = self
892 self.loggerDict[name] = rv
893 self._fixupParents(rv)
894 finally:
895 _releaseLock()
896 return rv
898 def _fixupParents(self, alogger):
900 Ensure that there are either loggers or placeholders all the way
901 from the specified logger to the root of the logger hierarchy.
903 name = alogger.name
904 i = string.rfind(name, ".")
905 rv = None
906 while (i > 0) and not rv:
907 substr = name[:i]
908 if not self.loggerDict.has_key(substr):
909 self.loggerDict[substr] = PlaceHolder(alogger)
910 else:
911 obj = self.loggerDict[substr]
912 if isinstance(obj, Logger):
913 rv = obj
914 else:
915 assert isinstance(obj, PlaceHolder)
916 obj.append(alogger)
917 i = string.rfind(name, ".", 0, i - 1)
918 if not rv:
919 rv = self.root
920 alogger.parent = rv
922 def _fixupChildren(self, ph, alogger):
924 Ensure that children of the placeholder ph are connected to the
925 specified logger.
927 name = alogger.name
928 namelen = len(name)
929 for c in ph.loggerMap.keys():
930 #The if means ... if not c.parent.name.startswith(nm)
931 #if string.find(c.parent.name, nm) <> 0:
932 if c.parent.name[:namelen] != name:
933 alogger.parent = c.parent
934 c.parent = alogger
936 #---------------------------------------------------------------------------
937 # Logger classes and functions
938 #---------------------------------------------------------------------------
940 class Logger(Filterer):
942 Instances of the Logger class represent a single logging channel. A
943 "logging channel" indicates an area of an application. Exactly how an
944 "area" is defined is up to the application developer. Since an
945 application can have any number of areas, logging channels are identified
946 by a unique string. Application areas can be nested (e.g. an area
947 of "input processing" might include sub-areas "read CSV files", "read
948 XLS files" and "read Gnumeric files"). To cater for this natural nesting,
949 channel names are organized into a namespace hierarchy where levels are
950 separated by periods, much like the Java or Python package namespace. So
951 in the instance given above, channel names might be "input" for the upper
952 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
953 There is no arbitrary limit to the depth of nesting.
955 def __init__(self, name, level=NOTSET):
957 Initialize the logger with a name and an optional level.
959 Filterer.__init__(self)
960 self.name = name
961 self.level = level
962 self.parent = None
963 self.propagate = 1
964 self.handlers = []
965 self.disabled = 0
967 def setLevel(self, level):
969 Set the logging level of this logger.
971 self.level = level
973 def debug(self, msg, *args, **kwargs):
975 Log 'msg % args' with severity 'DEBUG'.
977 To pass exception information, use the keyword argument exc_info with
978 a true value, e.g.
980 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
982 if self.isEnabledFor(DEBUG):
983 apply(self._log, (DEBUG, msg, args), kwargs)
985 def info(self, msg, *args, **kwargs):
987 Log 'msg % args' with severity 'INFO'.
989 To pass exception information, use the keyword argument exc_info with
990 a true value, e.g.
992 logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
994 if self.isEnabledFor(INFO):
995 apply(self._log, (INFO, msg, args), kwargs)
997 def warning(self, msg, *args, **kwargs):
999 Log 'msg % args' with severity 'WARNING'.
1001 To pass exception information, use the keyword argument exc_info with
1002 a true value, e.g.
1004 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
1006 if self.isEnabledFor(WARNING):
1007 apply(self._log, (WARNING, msg, args), kwargs)
1009 warn = warning
1011 def error(self, msg, *args, **kwargs):
1013 Log 'msg % args' with severity 'ERROR'.
1015 To pass exception information, use the keyword argument exc_info with
1016 a true value, e.g.
1018 logger.error("Houston, we have a %s", "major problem", exc_info=1)
1020 if self.isEnabledFor(ERROR):
1021 apply(self._log, (ERROR, msg, args), kwargs)
1023 def exception(self, msg, *args):
1025 Convenience method for logging an ERROR with exception information.
1027 apply(self.error, (msg,) + args, {'exc_info': 1})
1029 def critical(self, msg, *args, **kwargs):
1031 Log 'msg % args' with severity 'CRITICAL'.
1033 To pass exception information, use the keyword argument exc_info with
1034 a true value, e.g.
1036 logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
1038 if self.isEnabledFor(CRITICAL):
1039 apply(self._log, (CRITICAL, msg, args), kwargs)
1041 fatal = critical
1043 def log(self, level, msg, *args, **kwargs):
1045 Log 'msg % args' with the integer severity 'level'.
1047 To pass exception information, use the keyword argument exc_info with
1048 a true value, e.g.
1050 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1052 if type(level) != types.IntType:
1053 if raiseExceptions:
1054 raise TypeError, "level must be an integer"
1055 else:
1056 return
1057 if self.isEnabledFor(level):
1058 apply(self._log, (level, msg, args), kwargs)
1060 def findCaller(self):
1062 Find the stack frame of the caller so that we can note the source
1063 file name, line number and function name.
1065 f = currentframe().f_back
1066 rv = "(unknown file)", 0, "(unknown function)"
1067 while hasattr(f, "f_code"):
1068 co = f.f_code
1069 filename = os.path.normcase(co.co_filename)
1070 if filename == _srcfile:
1071 f = f.f_back
1072 continue
1073 rv = (filename, f.f_lineno, co.co_name)
1074 break
1075 return rv
1077 def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None):
1079 A factory method which can be overridden in subclasses to create
1080 specialized LogRecords.
1082 rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func)
1083 if extra is not None:
1084 for key in extra:
1085 if (key in ["message", "asctime"]) or (key in rv.__dict__):
1086 raise KeyError("Attempt to overwrite %r in LogRecord" % key)
1087 rv.__dict__[key] = extra[key]
1088 return rv
1090 def _log(self, level, msg, args, exc_info=None, extra=None):
1092 Low-level logging routine which creates a LogRecord and then calls
1093 all the handlers of this logger to handle the record.
1095 if _srcfile:
1096 fn, lno, func = self.findCaller()
1097 else:
1098 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1099 if exc_info:
1100 if type(exc_info) != types.TupleType:
1101 exc_info = sys.exc_info()
1102 record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra)
1103 self.handle(record)
1105 def handle(self, record):
1107 Call the handlers for the specified record.
1109 This method is used for unpickled records received from a socket, as
1110 well as those created locally. Logger-level filtering is applied.
1112 if (not self.disabled) and self.filter(record):
1113 self.callHandlers(record)
1115 def addHandler(self, hdlr):
1117 Add the specified handler to this logger.
1119 if not (hdlr in self.handlers):
1120 self.handlers.append(hdlr)
1122 def removeHandler(self, hdlr):
1124 Remove the specified handler from this logger.
1126 if hdlr in self.handlers:
1127 #hdlr.close()
1128 hdlr.acquire()
1129 try:
1130 self.handlers.remove(hdlr)
1131 finally:
1132 hdlr.release()
1134 def callHandlers(self, record):
1136 Pass a record to all relevant handlers.
1138 Loop through all handlers for this logger and its parents in the
1139 logger hierarchy. If no handler was found, output a one-off error
1140 message to sys.stderr. Stop searching up the hierarchy whenever a
1141 logger with the "propagate" attribute set to zero is found - that
1142 will be the last logger whose handlers are called.
1144 c = self
1145 found = 0
1146 while c:
1147 for hdlr in c.handlers:
1148 found = found + 1
1149 if record.levelno >= hdlr.level:
1150 hdlr.handle(record)
1151 if not c.propagate:
1152 c = None #break out
1153 else:
1154 c = c.parent
1155 if (found == 0) and raiseExceptions and not self.manager.emittedNoHandlerWarning:
1156 sys.stderr.write("No handlers could be found for logger"
1157 " \"%s\"\n" % self.name)
1158 self.manager.emittedNoHandlerWarning = 1
1160 def getEffectiveLevel(self):
1162 Get the effective level for this logger.
1164 Loop through this logger and its parents in the logger hierarchy,
1165 looking for a non-zero logging level. Return the first one found.
1167 logger = self
1168 while logger:
1169 if logger.level:
1170 return logger.level
1171 logger = logger.parent
1172 return NOTSET
1174 def isEnabledFor(self, level):
1176 Is this logger enabled for level 'level'?
1178 if self.manager.disable >= level:
1179 return 0
1180 return level >= self.getEffectiveLevel()
1182 class RootLogger(Logger):
1184 A root logger is not that different to any other logger, except that
1185 it must have a logging level and there is only one instance of it in
1186 the hierarchy.
1188 def __init__(self, level):
1190 Initialize the logger with the name "root".
1192 Logger.__init__(self, "root", level)
1194 _loggerClass = Logger
1196 class LoggerAdapter:
1198 An adapter for loggers which makes it easier to specify contextual
1199 information in logging output.
1202 def __init__(self, logger, extra):
1204 Initialize the adapter with a logger and a dict-like object which
1205 provides contextual information. This constructor signature allows
1206 easy stacking of LoggerAdapters, if so desired.
1208 You can effectively pass keyword arguments as shown in the
1209 following example:
1211 adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
1213 self.logger = logger
1214 self.extra = extra
1216 def process(self, msg, kwargs):
1218 Process the logging message and keyword arguments passed in to
1219 a logging call to insert contextual information. You can either
1220 manipulate the message itself, the keyword args or both. Return
1221 the message and kwargs modified (or not) to suit your needs.
1223 Normally, you'll only need to override this one method in a
1224 LoggerAdapter subclass for your specific needs.
1226 kwargs["extra"] = self.extra
1227 return msg, kwargs
1229 def debug(self, msg, *args, **kwargs):
1231 Delegate a debug call to the underlying logger, after adding
1232 contextual information from this adapter instance.
1234 msg, kwargs = self.process(msg, kwargs)
1235 self.logger.debug(msg, *args, **kwargs)
1237 def info(self, msg, *args, **kwargs):
1239 Delegate an info call to the underlying logger, after adding
1240 contextual information from this adapter instance.
1242 msg, kwargs = self.process(msg, kwargs)
1243 self.logger.info(msg, *args, **kwargs)
1245 def warning(self, msg, *args, **kwargs):
1247 Delegate a warning call to the underlying logger, after adding
1248 contextual information from this adapter instance.
1250 msg, kwargs = self.process(msg, kwargs)
1251 self.logger.warning(msg, *args, **kwargs)
1253 def error(self, msg, *args, **kwargs):
1255 Delegate an error call to the underlying logger, after adding
1256 contextual information from this adapter instance.
1258 msg, kwargs = self.process(msg, kwargs)
1259 self.logger.error(msg, *args, **kwargs)
1261 def exception(self, msg, *args, **kwargs):
1263 Delegate an exception call to the underlying logger, after adding
1264 contextual information from this adapter instance.
1266 msg, kwargs = self.process(msg, kwargs)
1267 kwargs["exc_info"] = 1
1268 self.logger.error(msg, *args, **kwargs)
1270 def critical(self, msg, *args, **kwargs):
1272 Delegate a critical call to the underlying logger, after adding
1273 contextual information from this adapter instance.
1275 msg, kwargs = self.process(msg, kwargs)
1276 self.logger.critical(msg, *args, **kwargs)
1278 def log(self, level, msg, *args, **kwargs):
1280 Delegate a log call to the underlying logger, after adding
1281 contextual information from this adapter instance.
1283 msg, kwargs = self.process(msg, kwargs)
1284 self.logger.log(level, msg, *args, **kwargs)
1286 root = RootLogger(WARNING)
1287 Logger.root = root
1288 Logger.manager = Manager(Logger.root)
1290 #---------------------------------------------------------------------------
1291 # Configuration classes and functions
1292 #---------------------------------------------------------------------------
1294 BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
1296 def basicConfig(**kwargs):
1298 Do basic configuration for the logging system.
1300 This function does nothing if the root logger already has handlers
1301 configured. It is a convenience method intended for use by simple scripts
1302 to do one-shot configuration of the logging package.
1304 The default behaviour is to create a StreamHandler which writes to
1305 sys.stderr, set a formatter using the BASIC_FORMAT format string, and
1306 add the handler to the root logger.
1308 A number of optional keyword arguments may be specified, which can alter
1309 the default behaviour.
1311 filename Specifies that a FileHandler be created, using the specified
1312 filename, rather than a StreamHandler.
1313 filemode Specifies the mode to open the file, if filename is specified
1314 (if filemode is unspecified, it defaults to 'a').
1315 format Use the specified format string for the handler.
1316 datefmt Use the specified date/time format.
1317 level Set the root logger level to the specified level.
1318 stream Use the specified stream to initialize the StreamHandler. Note
1319 that this argument is incompatible with 'filename' - if both
1320 are present, 'stream' is ignored.
1322 Note that you could specify a stream created using open(filename, mode)
1323 rather than passing the filename and mode in. However, it should be
1324 remembered that StreamHandler does not close its stream (since it may be
1325 using sys.stdout or sys.stderr), whereas FileHandler closes its stream
1326 when the handler is closed.
1328 if len(root.handlers) == 0:
1329 filename = kwargs.get("filename")
1330 if filename:
1331 mode = kwargs.get("filemode", 'a')
1332 hdlr = FileHandler(filename, mode)
1333 else:
1334 stream = kwargs.get("stream")
1335 hdlr = StreamHandler(stream)
1336 fs = kwargs.get("format", BASIC_FORMAT)
1337 dfs = kwargs.get("datefmt", None)
1338 fmt = Formatter(fs, dfs)
1339 hdlr.setFormatter(fmt)
1340 root.addHandler(hdlr)
1341 level = kwargs.get("level")
1342 if level is not None:
1343 root.setLevel(level)
1345 #---------------------------------------------------------------------------
1346 # Utility functions at module level.
1347 # Basically delegate everything to the root logger.
1348 #---------------------------------------------------------------------------
1350 def getLogger(name=None):
1352 Return a logger with the specified name, creating it if necessary.
1354 If no name is specified, return the root logger.
1356 if name:
1357 return Logger.manager.getLogger(name)
1358 else:
1359 return root
1361 #def getRootLogger():
1362 # """
1363 # Return the root logger.
1365 # Note that getLogger('') now does the same thing, so this function is
1366 # deprecated and may disappear in the future.
1367 # """
1368 # return root
1370 def critical(msg, *args, **kwargs):
1372 Log a message with severity 'CRITICAL' on the root logger.
1374 if len(root.handlers) == 0:
1375 basicConfig()
1376 apply(root.critical, (msg,)+args, kwargs)
1378 fatal = critical
1380 def error(msg, *args, **kwargs):
1382 Log a message with severity 'ERROR' on the root logger.
1384 if len(root.handlers) == 0:
1385 basicConfig()
1386 apply(root.error, (msg,)+args, kwargs)
1388 def exception(msg, *args):
1390 Log a message with severity 'ERROR' on the root logger,
1391 with exception information.
1393 apply(error, (msg,)+args, {'exc_info': 1})
1395 def warning(msg, *args, **kwargs):
1397 Log a message with severity 'WARNING' on the root logger.
1399 if len(root.handlers) == 0:
1400 basicConfig()
1401 apply(root.warning, (msg,)+args, kwargs)
1403 warn = warning
1405 def info(msg, *args, **kwargs):
1407 Log a message with severity 'INFO' on the root logger.
1409 if len(root.handlers) == 0:
1410 basicConfig()
1411 apply(root.info, (msg,)+args, kwargs)
1413 def debug(msg, *args, **kwargs):
1415 Log a message with severity 'DEBUG' on the root logger.
1417 if len(root.handlers) == 0:
1418 basicConfig()
1419 apply(root.debug, (msg,)+args, kwargs)
1421 def log(level, msg, *args, **kwargs):
1423 Log 'msg % args' with the integer severity 'level' on the root logger.
1425 if len(root.handlers) == 0:
1426 basicConfig()
1427 apply(root.log, (level, msg)+args, kwargs)
1429 def disable(level):
1431 Disable all logging calls less severe than 'level'.
1433 root.manager.disable = level
1435 def shutdown(handlerList=_handlerList):
1437 Perform any cleanup actions in the logging system (e.g. flushing
1438 buffers).
1440 Should be called at application exit.
1442 for h in handlerList[:]:
1443 #errors might occur, for example, if files are locked
1444 #we just ignore them if raiseExceptions is not set
1445 try:
1446 h.flush()
1447 h.close()
1448 except:
1449 if raiseExceptions:
1450 raise
1451 #else, swallow
1453 #Let's try and shutdown automatically on application exit...
1454 try:
1455 import atexit
1456 atexit.register(shutdown)
1457 except ImportError: # for Python versions < 2.0
1458 def exithook(status, old_exit=sys.exit):
1459 try:
1460 shutdown()
1461 finally:
1462 old_exit(status)
1464 sys.exit = exithook