Issue #4384: Added logging integration with warnings module using captureWarnings...
[python.git] / Lib / logging / __init__.py
blobc28d7c8650d9f400cadb9455c0941a12f5fc0cc6
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 __all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
30 'FATAL', 'FileHandler', 'Filter', 'Filterer', 'Formatter', 'Handler',
31 'INFO', 'LogRecord', 'Logger', 'Manager', 'NOTSET', 'PlaceHolder',
32 'RootLogger', 'StreamHandler', 'WARN', 'WARNING']
34 import sys, os, types, time, string, cStringIO, traceback
36 try:
37 import codecs
38 except ImportError:
39 codecs = None
41 try:
42 import thread
43 import threading
44 except ImportError:
45 thread = None
47 __author__ = "Vinay Sajip <vinay_sajip@red-dove.com>"
48 __status__ = "production"
49 __version__ = "0.5.0.6"
50 __date__ = "03 December 2008"
52 #---------------------------------------------------------------------------
53 # Miscellaneous module data
54 #---------------------------------------------------------------------------
57 # _srcfile is used when walking the stack to check when we've got the first
58 # caller stack frame.
60 if hasattr(sys, 'frozen'): #support for py2exe
61 _srcfile = "logging%s__init__%s" % (os.sep, __file__[-4:])
62 elif string.lower(__file__[-4:]) in ['.pyc', '.pyo']:
63 _srcfile = __file__[:-4] + '.py'
64 else:
65 _srcfile = __file__
66 _srcfile = os.path.normcase(_srcfile)
68 # next bit filched from 1.5.2's inspect.py
69 def 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
76 if hasattr(sys, '_getframe'): currentframe = lambda: sys._getframe(3)
77 # done filching
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
87 #_startTime is used as the base when calculating the relative time of events
89 _startTime = time.time()
92 #raiseExceptions is used to see if exceptions during handling should be
93 #propagated
95 raiseExceptions = 1
98 # If you don't want threading information in the log, set this to zero
100 logThreads = 1
103 # If you don't want process information in the log, set this to zero
105 logProcesses = 1
107 #---------------------------------------------------------------------------
108 # Level related stuff
109 #---------------------------------------------------------------------------
111 # Default levels and level names, these can be replaced with any positive set
112 # of values having corresponding names. There is a pseudo-level, NOTSET, which
113 # is only really there as a lower limit for user-defined levels. Handlers and
114 # loggers are initialized with NOTSET so that they will log all messages, even
115 # at user-defined levels.
118 CRITICAL = 50
119 FATAL = CRITICAL
120 ERROR = 40
121 WARNING = 30
122 WARN = WARNING
123 INFO = 20
124 DEBUG = 10
125 NOTSET = 0
127 _levelNames = {
128 CRITICAL : 'CRITICAL',
129 ERROR : 'ERROR',
130 WARNING : 'WARNING',
131 INFO : 'INFO',
132 DEBUG : 'DEBUG',
133 NOTSET : 'NOTSET',
134 'CRITICAL' : CRITICAL,
135 'ERROR' : ERROR,
136 'WARN' : WARNING,
137 'WARNING' : WARNING,
138 'INFO' : INFO,
139 'DEBUG' : DEBUG,
140 'NOTSET' : NOTSET,
143 def getLevelName(level):
145 Return the textual representation of logging level 'level'.
147 If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
148 INFO, DEBUG) then you get the corresponding string. If you have
149 associated levels with names using addLevelName then the name you have
150 associated with 'level' is returned.
152 If a numeric value corresponding to one of the defined levels is passed
153 in, the corresponding string representation is returned.
155 Otherwise, the string "Level %s" % level is returned.
157 return _levelNames.get(level, ("Level %s" % level))
159 def addLevelName(level, levelName):
161 Associate 'levelName' with 'level'.
163 This is used when converting levels to text during message formatting.
165 _acquireLock()
166 try: #unlikely to cause an exception, but you never know...
167 _levelNames[level] = levelName
168 _levelNames[levelName] = level
169 finally:
170 _releaseLock()
172 #---------------------------------------------------------------------------
173 # Thread-related stuff
174 #---------------------------------------------------------------------------
177 #_lock is used to serialize access to shared data structures in this module.
178 #This needs to be an RLock because fileConfig() creates Handlers and so
179 #might arbitrary user threads. Since Handler.__init__() updates the shared
180 #dictionary _handlers, it needs to acquire the lock. But if configuring,
181 #the lock would already have been acquired - so we need an RLock.
182 #The same argument applies to Loggers and Manager.loggerDict.
184 _lock = None
186 def _acquireLock():
188 Acquire the module-level lock for serializing access to shared data.
190 This should be released with _releaseLock().
192 global _lock
193 if (not _lock) and thread:
194 _lock = threading.RLock()
195 if _lock:
196 _lock.acquire()
198 def _releaseLock():
200 Release the module-level lock acquired by calling _acquireLock().
202 if _lock:
203 _lock.release()
205 #---------------------------------------------------------------------------
206 # The logging record
207 #---------------------------------------------------------------------------
209 class LogRecord:
211 A LogRecord instance represents an event being logged.
213 LogRecord instances are created every time something is logged. They
214 contain all the information pertinent to the event being logged. The
215 main information passed in is in msg and args, which are combined
216 using str(msg) % args to create the message field of the record. The
217 record also includes information such as when the record was created,
218 the source line where the logging call was made, and any exception
219 information to be logged.
221 def __init__(self, name, level, pathname, lineno,
222 msg, args, exc_info, func=None):
224 Initialize a logging record with interesting information.
226 ct = time.time()
227 self.name = name
228 self.msg = msg
230 # The following statement allows passing of a dictionary as a sole
231 # argument, so that you can do something like
232 # logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2})
233 # Suggested by Stefan Behnel.
234 # Note that without the test for args[0], we get a problem because
235 # during formatting, we test to see if the arg is present using
236 # 'if self.args:'. If the event being logged is e.g. 'Value is %d'
237 # and if the passed arg fails 'if self.args:' then no formatting
238 # is done. For example, logger.warn('Value is %d', 0) would log
239 # 'Value is %d' instead of 'Value is 0'.
240 # For the use case of passing a dictionary, this should not be a
241 # problem.
242 if args and len(args) == 1 and (
243 type(args[0]) == types.DictType
244 ) and args[0]:
245 args = args[0]
246 self.args = args
247 self.levelname = getLevelName(level)
248 self.levelno = level
249 self.pathname = pathname
250 try:
251 self.filename = os.path.basename(pathname)
252 self.module = os.path.splitext(self.filename)[0]
253 except (TypeError, ValueError, AttributeError):
254 self.filename = pathname
255 self.module = "Unknown module"
256 self.exc_info = exc_info
257 self.exc_text = None # used to cache the traceback text
258 self.lineno = lineno
259 self.funcName = func
260 self.created = ct
261 self.msecs = (ct - long(ct)) * 1000
262 self.relativeCreated = (self.created - _startTime) * 1000
263 if logThreads and thread:
264 self.thread = thread.get_ident()
265 self.threadName = threading.current_thread().name
266 else:
267 self.thread = None
268 self.threadName = None
269 if logProcesses and hasattr(os, 'getpid'):
270 self.process = os.getpid()
271 else:
272 self.process = None
274 def __str__(self):
275 return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
276 self.pathname, self.lineno, self.msg)
278 def getMessage(self):
280 Return the message for this LogRecord.
282 Return the message for this LogRecord after merging any user-supplied
283 arguments with the message.
285 if not hasattr(types, "UnicodeType"): #if no unicode support...
286 msg = str(self.msg)
287 else:
288 msg = self.msg
289 if type(msg) not in (types.UnicodeType, types.StringType):
290 try:
291 msg = str(self.msg)
292 except UnicodeError:
293 msg = self.msg #Defer encoding till later
294 if self.args:
295 msg = msg % self.args
296 return msg
298 def makeLogRecord(dict):
300 Make a LogRecord whose attributes are defined by the specified dictionary,
301 This function is useful for converting a logging event received over
302 a socket connection (which is sent as a dictionary) into a LogRecord
303 instance.
305 rv = LogRecord(None, None, "", 0, "", (), None, None)
306 rv.__dict__.update(dict)
307 return rv
309 #---------------------------------------------------------------------------
310 # Formatter classes and functions
311 #---------------------------------------------------------------------------
313 class Formatter:
315 Formatter instances are used to convert a LogRecord to text.
317 Formatters need to know how a LogRecord is constructed. They are
318 responsible for converting a LogRecord to (usually) a string which can
319 be interpreted by either a human or an external system. The base Formatter
320 allows a formatting string to be specified. If none is supplied, the
321 default value of "%s(message)\\n" is used.
323 The Formatter can be initialized with a format string which makes use of
324 knowledge of the LogRecord attributes - e.g. the default value mentioned
325 above makes use of the fact that the user's message and arguments are pre-
326 formatted into a LogRecord's message attribute. Currently, the useful
327 attributes in a LogRecord are described by:
329 %(name)s Name of the logger (logging channel)
330 %(levelno)s Numeric logging level for the message (DEBUG, INFO,
331 WARNING, ERROR, CRITICAL)
332 %(levelname)s Text logging level for the message ("DEBUG", "INFO",
333 "WARNING", "ERROR", "CRITICAL")
334 %(pathname)s Full pathname of the source file where the logging
335 call was issued (if available)
336 %(filename)s Filename portion of pathname
337 %(module)s Module (name portion of filename)
338 %(lineno)d Source line number where the logging call was issued
339 (if available)
340 %(funcName)s Function name
341 %(created)f Time when the LogRecord was created (time.time()
342 return value)
343 %(asctime)s Textual time when the LogRecord was created
344 %(msecs)d Millisecond portion of the creation time
345 %(relativeCreated)d Time in milliseconds when the LogRecord was created,
346 relative to the time the logging module was loaded
347 (typically at application startup time)
348 %(thread)d Thread ID (if available)
349 %(threadName)s Thread name (if available)
350 %(process)d Process ID (if available)
351 %(message)s The result of record.getMessage(), computed just as
352 the record is emitted
355 converter = time.localtime
357 def __init__(self, fmt=None, datefmt=None):
359 Initialize the formatter with specified format strings.
361 Initialize the formatter either with the specified format string, or a
362 default as described above. Allow for specialized date formatting with
363 the optional datefmt argument (if omitted, you get the ISO8601 format).
365 if fmt:
366 self._fmt = fmt
367 else:
368 self._fmt = "%(message)s"
369 self.datefmt = datefmt
371 def formatTime(self, record, datefmt=None):
373 Return the creation time of the specified LogRecord as formatted text.
375 This method should be called from format() by a formatter which
376 wants to make use of a formatted time. This method can be overridden
377 in formatters to provide for any specific requirement, but the
378 basic behaviour is as follows: if datefmt (a string) is specified,
379 it is used with time.strftime() to format the creation time of the
380 record. Otherwise, the ISO8601 format is used. The resulting
381 string is returned. This function uses a user-configurable function
382 to convert the creation time to a tuple. By default, time.localtime()
383 is used; to change this for a particular formatter instance, set the
384 'converter' attribute to a function with the same signature as
385 time.localtime() or time.gmtime(). To change it for all formatters,
386 for example if you want all logging times to be shown in GMT,
387 set the 'converter' attribute in the Formatter class.
389 ct = self.converter(record.created)
390 if datefmt:
391 s = time.strftime(datefmt, ct)
392 else:
393 t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
394 s = "%s,%03d" % (t, record.msecs)
395 return s
397 def formatException(self, ei):
399 Format and return the specified exception information as a string.
401 This default implementation just uses
402 traceback.print_exception()
404 sio = cStringIO.StringIO()
405 traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
406 s = sio.getvalue()
407 sio.close()
408 if s[-1:] == "\n":
409 s = s[:-1]
410 return s
412 def format(self, record):
414 Format the specified record as text.
416 The record's attribute dictionary is used as the operand to a
417 string formatting operation which yields the returned string.
418 Before formatting the dictionary, a couple of preparatory steps
419 are carried out. The message attribute of the record is computed
420 using LogRecord.getMessage(). If the formatting string contains
421 "%(asctime)", formatTime() is called to format the event time.
422 If there is exception information, it is formatted using
423 formatException() and appended to the message.
425 record.message = record.getMessage()
426 if string.find(self._fmt,"%(asctime)") >= 0:
427 record.asctime = self.formatTime(record, self.datefmt)
428 s = self._fmt % record.__dict__
429 if record.exc_info:
430 # Cache the traceback text to avoid converting it multiple times
431 # (it's constant anyway)
432 if not record.exc_text:
433 record.exc_text = self.formatException(record.exc_info)
434 if record.exc_text:
435 if s[-1:] != "\n":
436 s = s + "\n"
437 s = s + record.exc_text
438 return s
441 # The default formatter to use when no other is specified
443 _defaultFormatter = Formatter()
445 class BufferingFormatter:
447 A formatter suitable for formatting a number of records.
449 def __init__(self, linefmt=None):
451 Optionally specify a formatter which will be used to format each
452 individual record.
454 if linefmt:
455 self.linefmt = linefmt
456 else:
457 self.linefmt = _defaultFormatter
459 def formatHeader(self, records):
461 Return the header string for the specified records.
463 return ""
465 def formatFooter(self, records):
467 Return the footer string for the specified records.
469 return ""
471 def format(self, records):
473 Format the specified records and return the result as a string.
475 rv = ""
476 if len(records) > 0:
477 rv = rv + self.formatHeader(records)
478 for record in records:
479 rv = rv + self.linefmt.format(record)
480 rv = rv + self.formatFooter(records)
481 return rv
483 #---------------------------------------------------------------------------
484 # Filter classes and functions
485 #---------------------------------------------------------------------------
487 class Filter:
489 Filter instances are used to perform arbitrary filtering of LogRecords.
491 Loggers and Handlers can optionally use Filter instances to filter
492 records as desired. The base filter class only allows events which are
493 below a certain point in the logger hierarchy. For example, a filter
494 initialized with "A.B" will allow events logged by loggers "A.B",
495 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
496 initialized with the empty string, all events are passed.
498 def __init__(self, name=''):
500 Initialize a filter.
502 Initialize with the name of the logger which, together with its
503 children, will have its events allowed through the filter. If no
504 name is specified, allow every event.
506 self.name = name
507 self.nlen = len(name)
509 def filter(self, record):
511 Determine if the specified record is to be logged.
513 Is the specified record to be logged? Returns 0 for no, nonzero for
514 yes. If deemed appropriate, the record may be modified in-place.
516 if self.nlen == 0:
517 return 1
518 elif self.name == record.name:
519 return 1
520 elif string.find(record.name, self.name, 0, self.nlen) != 0:
521 return 0
522 return (record.name[self.nlen] == ".")
524 class Filterer:
526 A base class for loggers and handlers which allows them to share
527 common code.
529 def __init__(self):
531 Initialize the list of filters to be an empty list.
533 self.filters = []
535 def addFilter(self, filter):
537 Add the specified filter to this handler.
539 if not (filter in self.filters):
540 self.filters.append(filter)
542 def removeFilter(self, filter):
544 Remove the specified filter from this handler.
546 if filter in self.filters:
547 self.filters.remove(filter)
549 def filter(self, record):
551 Determine if a record is loggable by consulting all the filters.
553 The default is to allow the record to be logged; any filter can veto
554 this and the record is then dropped. Returns a zero value if a record
555 is to be dropped, else non-zero.
557 rv = 1
558 for f in self.filters:
559 if not f.filter(record):
560 rv = 0
561 break
562 return rv
564 #---------------------------------------------------------------------------
565 # Handler classes and functions
566 #---------------------------------------------------------------------------
568 _handlers = {} #repository of handlers (for flushing when shutdown called)
569 _handlerList = [] # added to allow handlers to be removed in reverse of order initialized
571 class Handler(Filterer):
573 Handler instances dispatch logging events to specific destinations.
575 The base handler class. Acts as a placeholder which defines the Handler
576 interface. Handlers can optionally use Formatter instances to format
577 records as desired. By default, no formatter is specified; in this case,
578 the 'raw' message as determined by record.message is logged.
580 def __init__(self, level=NOTSET):
582 Initializes the instance - basically setting the formatter to None
583 and the filter list to empty.
585 Filterer.__init__(self)
586 self.level = level
587 self.formatter = None
588 #get the module data lock, as we're updating a shared structure.
589 _acquireLock()
590 try: #unlikely to raise an exception, but you never know...
591 _handlers[self] = 1
592 _handlerList.insert(0, self)
593 finally:
594 _releaseLock()
595 self.createLock()
597 def createLock(self):
599 Acquire a thread lock for serializing access to the underlying I/O.
601 if thread:
602 self.lock = threading.RLock()
603 else:
604 self.lock = None
606 def acquire(self):
608 Acquire the I/O thread lock.
610 if self.lock:
611 self.lock.acquire()
613 def release(self):
615 Release the I/O thread lock.
617 if self.lock:
618 self.lock.release()
620 def setLevel(self, level):
622 Set the logging level of this handler.
624 self.level = level
626 def format(self, record):
628 Format the specified record.
630 If a formatter is set, use it. Otherwise, use the default formatter
631 for the module.
633 if self.formatter:
634 fmt = self.formatter
635 else:
636 fmt = _defaultFormatter
637 return fmt.format(record)
639 def emit(self, record):
641 Do whatever it takes to actually log the specified logging record.
643 This version is intended to be implemented by subclasses and so
644 raises a NotImplementedError.
646 raise NotImplementedError, 'emit must be implemented '\
647 'by Handler subclasses'
649 def handle(self, record):
651 Conditionally emit the specified logging record.
653 Emission depends on filters which may have been added to the handler.
654 Wrap the actual emission of the record with acquisition/release of
655 the I/O thread lock. Returns whether the filter passed the record for
656 emission.
658 rv = self.filter(record)
659 if rv:
660 self.acquire()
661 try:
662 self.emit(record)
663 finally:
664 self.release()
665 return rv
667 def setFormatter(self, fmt):
669 Set the formatter for this handler.
671 self.formatter = fmt
673 def flush(self):
675 Ensure all logging output has been flushed.
677 This version does nothing and is intended to be implemented by
678 subclasses.
680 pass
682 def close(self):
684 Tidy up any resources used by the handler.
686 This version does removes the handler from an internal list
687 of handlers which is closed when shutdown() is called. Subclasses
688 should ensure that this gets called from overridden close()
689 methods.
691 #get the module data lock, as we're updating a shared structure.
692 _acquireLock()
693 try: #unlikely to raise an exception, but you never know...
694 del _handlers[self]
695 _handlerList.remove(self)
696 finally:
697 _releaseLock()
699 def handleError(self, record):
701 Handle errors which occur during an emit() call.
703 This method should be called from handlers when an exception is
704 encountered during an emit() call. If raiseExceptions is false,
705 exceptions get silently ignored. This is what is mostly wanted
706 for a logging system - most users will not care about errors in
707 the logging system, they are more interested in application errors.
708 You could, however, replace this with a custom handler if you wish.
709 The record which was being processed is passed in to this method.
711 if raiseExceptions:
712 ei = sys.exc_info()
713 traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
714 del ei
716 class StreamHandler(Handler):
718 A handler class which writes logging records, appropriately formatted,
719 to a stream. Note that this class does not close the stream, as
720 sys.stdout or sys.stderr may be used.
723 def __init__(self, strm=None):
725 Initialize the handler.
727 If strm is not specified, sys.stderr is used.
729 Handler.__init__(self)
730 if strm is None:
731 strm = sys.stderr
732 self.stream = strm
733 self.formatter = None
735 def flush(self):
737 Flushes the stream.
739 if self.stream and hasattr(self.stream, "flush"):
740 self.stream.flush()
742 def emit(self, record):
744 Emit a record.
746 If a formatter is specified, it is used to format the record.
747 The record is then written to the stream with a trailing newline. If
748 exception information is present, it is formatted using
749 traceback.print_exception and appended to the stream. If the stream
750 has an 'encoding' attribute, it is used to encode the message before
751 output to the stream.
753 try:
754 msg = self.format(record)
755 fs = "%s\n"
756 if not hasattr(types, "UnicodeType"): #if no unicode support...
757 self.stream.write(fs % msg)
758 else:
759 try:
760 if getattr(self.stream, 'encoding', None) is not None:
761 self.stream.write(fs % msg.encode(self.stream.encoding))
762 else:
763 self.stream.write(fs % msg)
764 except UnicodeError:
765 self.stream.write(fs % msg.encode("UTF-8"))
766 self.flush()
767 except (KeyboardInterrupt, SystemExit):
768 raise
769 except:
770 self.handleError(record)
772 class FileHandler(StreamHandler):
774 A handler class which writes formatted logging records to disk files.
776 def __init__(self, filename, mode='a', encoding=None, delay=0):
778 Open the specified file and use it as the stream for logging.
780 #keep the absolute path, otherwise derived classes which use this
781 #may come a cropper when the current directory changes
782 if codecs is None:
783 encoding = None
784 self.baseFilename = os.path.abspath(filename)
785 self.mode = mode
786 self.encoding = encoding
787 if delay:
788 self.stream = None
789 else:
790 stream = self._open()
791 StreamHandler.__init__(self, stream)
793 def close(self):
795 Closes the stream.
797 if self.stream:
798 self.flush()
799 if hasattr(self.stream, "close"):
800 self.stream.close()
801 StreamHandler.close(self)
802 self.stream = None
804 def _open(self):
806 Open the current base file with the (original) mode and encoding.
807 Return the resulting stream.
809 if self.encoding is None:
810 stream = open(self.baseFilename, self.mode)
811 else:
812 stream = codecs.open(self.baseFilename, self.mode, self.encoding)
813 return stream
815 def emit(self, record):
817 Emit a record.
819 If the stream was not opened because 'delay' was specified in the
820 constructor, open it before calling the superclass's emit.
822 if self.stream is None:
823 stream = self._open()
824 StreamHandler.__init__(self, stream)
825 StreamHandler.emit(self, record)
827 #---------------------------------------------------------------------------
828 # Manager classes and functions
829 #---------------------------------------------------------------------------
831 class PlaceHolder:
833 PlaceHolder instances are used in the Manager logger hierarchy to take
834 the place of nodes for which no loggers have been defined. This class is
835 intended for internal use only and not as part of the public API.
837 def __init__(self, alogger):
839 Initialize with the specified logger being a child of this placeholder.
841 #self.loggers = [alogger]
842 self.loggerMap = { alogger : None }
844 def append(self, alogger):
846 Add the specified logger as a child of this placeholder.
848 #if alogger not in self.loggers:
849 if not self.loggerMap.has_key(alogger):
850 #self.loggers.append(alogger)
851 self.loggerMap[alogger] = None
854 # Determine which class to use when instantiating loggers.
856 _loggerClass = None
858 def setLoggerClass(klass):
860 Set the class to be used when instantiating a logger. The class should
861 define __init__() such that only a name argument is required, and the
862 __init__() should call Logger.__init__()
864 if klass != Logger:
865 if not issubclass(klass, Logger):
866 raise TypeError, "logger not derived from logging.Logger: " + \
867 klass.__name__
868 global _loggerClass
869 _loggerClass = klass
871 def getLoggerClass():
873 Return the class to be used when instantiating a logger.
876 return _loggerClass
878 class Manager:
880 There is [under normal circumstances] just one Manager instance, which
881 holds the hierarchy of loggers.
883 def __init__(self, rootnode):
885 Initialize the manager with the root node of the logger hierarchy.
887 self.root = rootnode
888 self.disable = 0
889 self.emittedNoHandlerWarning = 0
890 self.loggerDict = {}
892 def getLogger(self, name):
894 Get a logger with the specified name (channel name), creating it
895 if it doesn't yet exist. This name is a dot-separated hierarchical
896 name, such as "a", "a.b", "a.b.c" or similar.
898 If a PlaceHolder existed for the specified name [i.e. the logger
899 didn't exist but a child of it did], replace it with the created
900 logger and fix up the parent/child references which pointed to the
901 placeholder to now point to the logger.
903 rv = None
904 _acquireLock()
905 try:
906 if name in self.loggerDict:
907 rv = self.loggerDict[name]
908 if isinstance(rv, PlaceHolder):
909 ph = rv
910 rv = _loggerClass(name)
911 rv.manager = self
912 self.loggerDict[name] = rv
913 self._fixupChildren(ph, rv)
914 self._fixupParents(rv)
915 else:
916 rv = _loggerClass(name)
917 rv.manager = self
918 self.loggerDict[name] = rv
919 self._fixupParents(rv)
920 finally:
921 _releaseLock()
922 return rv
924 def _fixupParents(self, alogger):
926 Ensure that there are either loggers or placeholders all the way
927 from the specified logger to the root of the logger hierarchy.
929 name = alogger.name
930 i = string.rfind(name, ".")
931 rv = None
932 while (i > 0) and not rv:
933 substr = name[:i]
934 if substr not in self.loggerDict:
935 self.loggerDict[substr] = PlaceHolder(alogger)
936 else:
937 obj = self.loggerDict[substr]
938 if isinstance(obj, Logger):
939 rv = obj
940 else:
941 assert isinstance(obj, PlaceHolder)
942 obj.append(alogger)
943 i = string.rfind(name, ".", 0, i - 1)
944 if not rv:
945 rv = self.root
946 alogger.parent = rv
948 def _fixupChildren(self, ph, alogger):
950 Ensure that children of the placeholder ph are connected to the
951 specified logger.
953 name = alogger.name
954 namelen = len(name)
955 for c in ph.loggerMap.keys():
956 #The if means ... if not c.parent.name.startswith(nm)
957 #if string.find(c.parent.name, nm) <> 0:
958 if c.parent.name[:namelen] != name:
959 alogger.parent = c.parent
960 c.parent = alogger
962 #---------------------------------------------------------------------------
963 # Logger classes and functions
964 #---------------------------------------------------------------------------
966 class Logger(Filterer):
968 Instances of the Logger class represent a single logging channel. A
969 "logging channel" indicates an area of an application. Exactly how an
970 "area" is defined is up to the application developer. Since an
971 application can have any number of areas, logging channels are identified
972 by a unique string. Application areas can be nested (e.g. an area
973 of "input processing" might include sub-areas "read CSV files", "read
974 XLS files" and "read Gnumeric files"). To cater for this natural nesting,
975 channel names are organized into a namespace hierarchy where levels are
976 separated by periods, much like the Java or Python package namespace. So
977 in the instance given above, channel names might be "input" for the upper
978 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
979 There is no arbitrary limit to the depth of nesting.
981 def __init__(self, name, level=NOTSET):
983 Initialize the logger with a name and an optional level.
985 Filterer.__init__(self)
986 self.name = name
987 self.level = level
988 self.parent = None
989 self.propagate = 1
990 self.handlers = []
991 self.disabled = 0
993 def setLevel(self, level):
995 Set the logging level of this logger.
997 self.level = level
999 def debug(self, msg, *args, **kwargs):
1001 Log 'msg % args' with severity 'DEBUG'.
1003 To pass exception information, use the keyword argument exc_info with
1004 a true value, e.g.
1006 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
1008 if self.isEnabledFor(DEBUG):
1009 self._log(DEBUG, msg, args, **kwargs)
1011 def info(self, msg, *args, **kwargs):
1013 Log 'msg % args' with severity 'INFO'.
1015 To pass exception information, use the keyword argument exc_info with
1016 a true value, e.g.
1018 logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
1020 if self.isEnabledFor(INFO):
1021 self._log(INFO, msg, args, **kwargs)
1023 def warning(self, msg, *args, **kwargs):
1025 Log 'msg % args' with severity 'WARNING'.
1027 To pass exception information, use the keyword argument exc_info with
1028 a true value, e.g.
1030 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
1032 if self.isEnabledFor(WARNING):
1033 self._log(WARNING, msg, args, **kwargs)
1035 warn = warning
1037 def error(self, msg, *args, **kwargs):
1039 Log 'msg % args' with severity 'ERROR'.
1041 To pass exception information, use the keyword argument exc_info with
1042 a true value, e.g.
1044 logger.error("Houston, we have a %s", "major problem", exc_info=1)
1046 if self.isEnabledFor(ERROR):
1047 self._log(ERROR, msg, args, **kwargs)
1049 def exception(self, msg, *args):
1051 Convenience method for logging an ERROR with exception information.
1053 self.error(*((msg,) + args), **{'exc_info': 1})
1055 def critical(self, msg, *args, **kwargs):
1057 Log 'msg % args' with severity 'CRITICAL'.
1059 To pass exception information, use the keyword argument exc_info with
1060 a true value, e.g.
1062 logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
1064 if self.isEnabledFor(CRITICAL):
1065 self._log(CRITICAL, msg, args, **kwargs)
1067 fatal = critical
1069 def log(self, level, msg, *args, **kwargs):
1071 Log 'msg % args' with the integer severity 'level'.
1073 To pass exception information, use the keyword argument exc_info with
1074 a true value, e.g.
1076 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1078 if type(level) != types.IntType:
1079 if raiseExceptions:
1080 raise TypeError, "level must be an integer"
1081 else:
1082 return
1083 if self.isEnabledFor(level):
1084 self._log(level, msg, args, **kwargs)
1086 def findCaller(self):
1088 Find the stack frame of the caller so that we can note the source
1089 file name, line number and function name.
1091 f = currentframe().f_back
1092 rv = "(unknown file)", 0, "(unknown function)"
1093 while hasattr(f, "f_code"):
1094 co = f.f_code
1095 filename = os.path.normcase(co.co_filename)
1096 if filename == _srcfile:
1097 f = f.f_back
1098 continue
1099 rv = (filename, f.f_lineno, co.co_name)
1100 break
1101 return rv
1103 def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None):
1105 A factory method which can be overridden in subclasses to create
1106 specialized LogRecords.
1108 rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func)
1109 if extra is not None:
1110 for key in extra:
1111 if (key in ["message", "asctime"]) or (key in rv.__dict__):
1112 raise KeyError("Attempt to overwrite %r in LogRecord" % key)
1113 rv.__dict__[key] = extra[key]
1114 return rv
1116 def _log(self, level, msg, args, exc_info=None, extra=None):
1118 Low-level logging routine which creates a LogRecord and then calls
1119 all the handlers of this logger to handle the record.
1121 if _srcfile:
1122 fn, lno, func = self.findCaller()
1123 else:
1124 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1125 if exc_info:
1126 if type(exc_info) != types.TupleType:
1127 exc_info = sys.exc_info()
1128 record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra)
1129 self.handle(record)
1131 def handle(self, record):
1133 Call the handlers for the specified record.
1135 This method is used for unpickled records received from a socket, as
1136 well as those created locally. Logger-level filtering is applied.
1138 if (not self.disabled) and self.filter(record):
1139 self.callHandlers(record)
1141 def addHandler(self, hdlr):
1143 Add the specified handler to this logger.
1145 if not (hdlr in self.handlers):
1146 self.handlers.append(hdlr)
1148 def removeHandler(self, hdlr):
1150 Remove the specified handler from this logger.
1152 if hdlr in self.handlers:
1153 #hdlr.close()
1154 hdlr.acquire()
1155 try:
1156 self.handlers.remove(hdlr)
1157 finally:
1158 hdlr.release()
1160 def callHandlers(self, record):
1162 Pass a record to all relevant handlers.
1164 Loop through all handlers for this logger and its parents in the
1165 logger hierarchy. If no handler was found, output a one-off error
1166 message to sys.stderr. Stop searching up the hierarchy whenever a
1167 logger with the "propagate" attribute set to zero is found - that
1168 will be the last logger whose handlers are called.
1170 c = self
1171 found = 0
1172 while c:
1173 for hdlr in c.handlers:
1174 found = found + 1
1175 if record.levelno >= hdlr.level:
1176 hdlr.handle(record)
1177 if not c.propagate:
1178 c = None #break out
1179 else:
1180 c = c.parent
1181 if (found == 0) and raiseExceptions and not self.manager.emittedNoHandlerWarning:
1182 sys.stderr.write("No handlers could be found for logger"
1183 " \"%s\"\n" % self.name)
1184 self.manager.emittedNoHandlerWarning = 1
1186 def getEffectiveLevel(self):
1188 Get the effective level for this logger.
1190 Loop through this logger and its parents in the logger hierarchy,
1191 looking for a non-zero logging level. Return the first one found.
1193 logger = self
1194 while logger:
1195 if logger.level:
1196 return logger.level
1197 logger = logger.parent
1198 return NOTSET
1200 def isEnabledFor(self, level):
1202 Is this logger enabled for level 'level'?
1204 if self.manager.disable >= level:
1205 return 0
1206 return level >= self.getEffectiveLevel()
1208 class RootLogger(Logger):
1210 A root logger is not that different to any other logger, except that
1211 it must have a logging level and there is only one instance of it in
1212 the hierarchy.
1214 def __init__(self, level):
1216 Initialize the logger with the name "root".
1218 Logger.__init__(self, "root", level)
1220 _loggerClass = Logger
1222 class LoggerAdapter:
1224 An adapter for loggers which makes it easier to specify contextual
1225 information in logging output.
1228 def __init__(self, logger, extra):
1230 Initialize the adapter with a logger and a dict-like object which
1231 provides contextual information. This constructor signature allows
1232 easy stacking of LoggerAdapters, if so desired.
1234 You can effectively pass keyword arguments as shown in the
1235 following example:
1237 adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
1239 self.logger = logger
1240 self.extra = extra
1242 def process(self, msg, kwargs):
1244 Process the logging message and keyword arguments passed in to
1245 a logging call to insert contextual information. You can either
1246 manipulate the message itself, the keyword args or both. Return
1247 the message and kwargs modified (or not) to suit your needs.
1249 Normally, you'll only need to override this one method in a
1250 LoggerAdapter subclass for your specific needs.
1252 kwargs["extra"] = self.extra
1253 return msg, kwargs
1255 def debug(self, msg, *args, **kwargs):
1257 Delegate a debug call to the underlying logger, after adding
1258 contextual information from this adapter instance.
1260 msg, kwargs = self.process(msg, kwargs)
1261 self.logger.debug(msg, *args, **kwargs)
1263 def info(self, msg, *args, **kwargs):
1265 Delegate an info call to the underlying logger, after adding
1266 contextual information from this adapter instance.
1268 msg, kwargs = self.process(msg, kwargs)
1269 self.logger.info(msg, *args, **kwargs)
1271 def warning(self, msg, *args, **kwargs):
1273 Delegate a warning call to the underlying logger, after adding
1274 contextual information from this adapter instance.
1276 msg, kwargs = self.process(msg, kwargs)
1277 self.logger.warning(msg, *args, **kwargs)
1279 def error(self, msg, *args, **kwargs):
1281 Delegate an error call to the underlying logger, after adding
1282 contextual information from this adapter instance.
1284 msg, kwargs = self.process(msg, kwargs)
1285 self.logger.error(msg, *args, **kwargs)
1287 def exception(self, msg, *args, **kwargs):
1289 Delegate an exception call to the underlying logger, after adding
1290 contextual information from this adapter instance.
1292 msg, kwargs = self.process(msg, kwargs)
1293 kwargs["exc_info"] = 1
1294 self.logger.error(msg, *args, **kwargs)
1296 def critical(self, msg, *args, **kwargs):
1298 Delegate a critical call to the underlying logger, after adding
1299 contextual information from this adapter instance.
1301 msg, kwargs = self.process(msg, kwargs)
1302 self.logger.critical(msg, *args, **kwargs)
1304 def log(self, level, msg, *args, **kwargs):
1306 Delegate a log call to the underlying logger, after adding
1307 contextual information from this adapter instance.
1309 msg, kwargs = self.process(msg, kwargs)
1310 self.logger.log(level, msg, *args, **kwargs)
1312 root = RootLogger(WARNING)
1313 Logger.root = root
1314 Logger.manager = Manager(Logger.root)
1316 #---------------------------------------------------------------------------
1317 # Configuration classes and functions
1318 #---------------------------------------------------------------------------
1320 BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
1322 def basicConfig(**kwargs):
1324 Do basic configuration for the logging system.
1326 This function does nothing if the root logger already has handlers
1327 configured. It is a convenience method intended for use by simple scripts
1328 to do one-shot configuration of the logging package.
1330 The default behaviour is to create a StreamHandler which writes to
1331 sys.stderr, set a formatter using the BASIC_FORMAT format string, and
1332 add the handler to the root logger.
1334 A number of optional keyword arguments may be specified, which can alter
1335 the default behaviour.
1337 filename Specifies that a FileHandler be created, using the specified
1338 filename, rather than a StreamHandler.
1339 filemode Specifies the mode to open the file, if filename is specified
1340 (if filemode is unspecified, it defaults to 'a').
1341 format Use the specified format string for the handler.
1342 datefmt Use the specified date/time format.
1343 level Set the root logger level to the specified level.
1344 stream Use the specified stream to initialize the StreamHandler. Note
1345 that this argument is incompatible with 'filename' - if both
1346 are present, 'stream' is ignored.
1348 Note that you could specify a stream created using open(filename, mode)
1349 rather than passing the filename and mode in. However, it should be
1350 remembered that StreamHandler does not close its stream (since it may be
1351 using sys.stdout or sys.stderr), whereas FileHandler closes its stream
1352 when the handler is closed.
1354 if len(root.handlers) == 0:
1355 filename = kwargs.get("filename")
1356 if filename:
1357 mode = kwargs.get("filemode", 'a')
1358 hdlr = FileHandler(filename, mode)
1359 else:
1360 stream = kwargs.get("stream")
1361 hdlr = StreamHandler(stream)
1362 fs = kwargs.get("format", BASIC_FORMAT)
1363 dfs = kwargs.get("datefmt", None)
1364 fmt = Formatter(fs, dfs)
1365 hdlr.setFormatter(fmt)
1366 root.addHandler(hdlr)
1367 level = kwargs.get("level")
1368 if level is not None:
1369 root.setLevel(level)
1371 #---------------------------------------------------------------------------
1372 # Utility functions at module level.
1373 # Basically delegate everything to the root logger.
1374 #---------------------------------------------------------------------------
1376 def getLogger(name=None):
1378 Return a logger with the specified name, creating it if necessary.
1380 If no name is specified, return the root logger.
1382 if name:
1383 return Logger.manager.getLogger(name)
1384 else:
1385 return root
1387 #def getRootLogger():
1388 # """
1389 # Return the root logger.
1391 # Note that getLogger('') now does the same thing, so this function is
1392 # deprecated and may disappear in the future.
1393 # """
1394 # return root
1396 def critical(msg, *args, **kwargs):
1398 Log a message with severity 'CRITICAL' on the root logger.
1400 if len(root.handlers) == 0:
1401 basicConfig()
1402 root.critical(*((msg,)+args), **kwargs)
1404 fatal = critical
1406 def error(msg, *args, **kwargs):
1408 Log a message with severity 'ERROR' on the root logger.
1410 if len(root.handlers) == 0:
1411 basicConfig()
1412 root.error(*((msg,)+args), **kwargs)
1414 def exception(msg, *args):
1416 Log a message with severity 'ERROR' on the root logger,
1417 with exception information.
1419 error(*((msg,)+args), **{'exc_info': 1})
1421 def warning(msg, *args, **kwargs):
1423 Log a message with severity 'WARNING' on the root logger.
1425 if len(root.handlers) == 0:
1426 basicConfig()
1427 root.warning(*((msg,)+args), **kwargs)
1429 warn = warning
1431 def info(msg, *args, **kwargs):
1433 Log a message with severity 'INFO' on the root logger.
1435 if len(root.handlers) == 0:
1436 basicConfig()
1437 root.info(*((msg,)+args), **kwargs)
1439 def debug(msg, *args, **kwargs):
1441 Log a message with severity 'DEBUG' on the root logger.
1443 if len(root.handlers) == 0:
1444 basicConfig()
1445 root.debug(*((msg,)+args), **kwargs)
1447 def log(level, msg, *args, **kwargs):
1449 Log 'msg % args' with the integer severity 'level' on the root logger.
1451 if len(root.handlers) == 0:
1452 basicConfig()
1453 root.log(*((level, msg)+args), **kwargs)
1455 def disable(level):
1457 Disable all logging calls less severe than 'level'.
1459 root.manager.disable = level
1461 def shutdown(handlerList=_handlerList):
1463 Perform any cleanup actions in the logging system (e.g. flushing
1464 buffers).
1466 Should be called at application exit.
1468 for h in handlerList[:]:
1469 #errors might occur, for example, if files are locked
1470 #we just ignore them if raiseExceptions is not set
1471 try:
1472 h.flush()
1473 h.close()
1474 except:
1475 if raiseExceptions:
1476 raise
1477 #else, swallow
1479 #Let's try and shutdown automatically on application exit...
1480 try:
1481 import atexit
1482 atexit.register(shutdown)
1483 except ImportError: # for Python versions < 2.0
1484 def exithook(status, old_exit=sys.exit):
1485 try:
1486 shutdown()
1487 finally:
1488 old_exit(status)
1490 sys.exit = exithook
1492 # Null handler
1494 class NullHandler(Handler):
1496 This handler does nothing. It's intended to be used to avoid the
1497 "No handlers could be found for logger XXX" one-off warning. This is
1498 important for library code, which may contain code to log events. If a user
1499 of the library does not configure logging, the one-off warning might be
1500 produced; to avoid this, the library developer simply needs to instantiate
1501 a NullHandler and add it to the top-level logger of the library module or
1502 package.
1504 def emit(self, record):
1505 pass
1507 # Warnings integration
1509 _warnings_showwarning = None
1511 def _showwarning(message, category, filename, lineno, file=None, line=None):
1513 Implementation of showwarnings which redirects to logging, which will first
1514 check to see if the file parameter is None. If a file is specified, it will
1515 delegate to the original warnings implementation of showwarning. Otherwise,
1516 it will call warnings.formatwarning and will log the resulting string to a
1517 warnings logger named "py.warnings" with level logging.WARNING.
1519 if file is not None:
1520 if _warnings_showwarning is not None:
1521 _warnings_showwarning(message, category, filename, lineno, file, line)
1522 else:
1523 import warnings
1524 s = warnings.formatwarning(message, category, filename, lineno, line)
1525 logger = getLogger("py.warnings")
1526 if not logger.handlers:
1527 logger.addHandler(NullHandler())
1528 logger.warning("%s", s)
1530 def captureWarnings(capture):
1532 If capture is true, redirect all warnings to the logging package.
1533 If capture is False, ensure that warnings are not redirected to logging
1534 but to their original destinations.
1536 import warnings
1537 global _warnings_showwarning
1538 if capture:
1539 if _warnings_showwarning is None:
1540 _warnings_showwarning = warnings.showwarning
1541 warnings.showwarning = _showwarning
1542 else:
1543 if _warnings_showwarning is not None:
1544 warnings.showwarning = _warnings_showwarning
1545 _warnings_showwarning = None