Exception handling now raises KeyboardInterrupt and SystemExit rather than passing...
[python.git] / Lib / logging / __init__.py
blob5a0b0f50213dce22df1c43f73fd4b4b73e81d63f
1 # Copyright 2001-2005 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-2004 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__ = "beta"
44 __version__ = "0.4.9.7"
45 __date__ = "07 October 2005"
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 = sys._getframe
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
92 #---------------------------------------------------------------------------
93 # Level related stuff
94 #---------------------------------------------------------------------------
96 # Default levels and level names, these can be replaced with any positive set
97 # of values having corresponding names. There is a pseudo-level, NOTSET, which
98 # is only really there as a lower limit for user-defined levels. Handlers and
99 # loggers are initialized with NOTSET so that they will log all messages, even
100 # at user-defined levels.
103 CRITICAL = 50
104 FATAL = CRITICAL
105 ERROR = 40
106 WARNING = 30
107 WARN = WARNING
108 INFO = 20
109 DEBUG = 10
110 NOTSET = 0
112 _levelNames = {
113 CRITICAL : 'CRITICAL',
114 ERROR : 'ERROR',
115 WARNING : 'WARNING',
116 INFO : 'INFO',
117 DEBUG : 'DEBUG',
118 NOTSET : 'NOTSET',
119 'CRITICAL' : CRITICAL,
120 'ERROR' : ERROR,
121 'WARN' : WARNING,
122 'WARNING' : WARNING,
123 'INFO' : INFO,
124 'DEBUG' : DEBUG,
125 'NOTSET' : NOTSET,
128 def getLevelName(level):
130 Return the textual representation of logging level 'level'.
132 If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
133 INFO, DEBUG) then you get the corresponding string. If you have
134 associated levels with names using addLevelName then the name you have
135 associated with 'level' is returned.
137 If a numeric value corresponding to one of the defined levels is passed
138 in, the corresponding string representation is returned.
140 Otherwise, the string "Level %s" % level is returned.
142 return _levelNames.get(level, ("Level %s" % level))
144 def addLevelName(level, levelName):
146 Associate 'levelName' with 'level'.
148 This is used when converting levels to text during message formatting.
150 _acquireLock()
151 try: #unlikely to cause an exception, but you never know...
152 _levelNames[level] = levelName
153 _levelNames[levelName] = level
154 finally:
155 _releaseLock()
157 #---------------------------------------------------------------------------
158 # Thread-related stuff
159 #---------------------------------------------------------------------------
162 #_lock is used to serialize access to shared data structures in this module.
163 #This needs to be an RLock because fileConfig() creates Handlers and so
164 #might arbitrary user threads. Since Handler.__init__() updates the shared
165 #dictionary _handlers, it needs to acquire the lock. But if configuring,
166 #the lock would already have been acquired - so we need an RLock.
167 #The same argument applies to Loggers and Manager.loggerDict.
169 _lock = None
171 def _acquireLock():
173 Acquire the module-level lock for serializing access to shared data.
175 This should be released with _releaseLock().
177 global _lock
178 if (not _lock) and thread:
179 _lock = threading.RLock()
180 if _lock:
181 _lock.acquire()
183 def _releaseLock():
185 Release the module-level lock acquired by calling _acquireLock().
187 if _lock:
188 _lock.release()
190 #---------------------------------------------------------------------------
191 # The logging record
192 #---------------------------------------------------------------------------
194 class LogRecord:
196 A LogRecord instance represents an event being logged.
198 LogRecord instances are created every time something is logged. They
199 contain all the information pertinent to the event being logged. The
200 main information passed in is in msg and args, which are combined
201 using str(msg) % args to create the message field of the record. The
202 record also includes information such as when the record was created,
203 the source line where the logging call was made, and any exception
204 information to be logged.
206 def __init__(self, name, level, pathname, lineno, msg, args, exc_info):
208 Initialize a logging record with interesting information.
210 ct = time.time()
211 self.name = name
212 self.msg = msg
214 # The following statement allows passing of a dictionary as a sole
215 # argument, so that you can do something like
216 # logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2})
217 # Suggested by Stefan Behnel.
218 # Note that without the test for args[0], we get a problem because
219 # during formatting, we test to see if the arg is present using
220 # 'if self.args:'. If the event being logged is e.g. 'Value is %d'
221 # and if the passed arg fails 'if self.args:' then no formatting
222 # is done. For example, logger.warn('Value is %d', 0) would log
223 # 'Value is %d' instead of 'Value is 0'.
224 # For the use case of passing a dictionary, this should not be a
225 # problem.
226 if args and (len(args) == 1) and args[0] and (type(args[0]) == types.DictType):
227 args = args[0]
228 self.args = args
229 self.levelname = getLevelName(level)
230 self.levelno = level
231 self.pathname = pathname
232 try:
233 self.filename = os.path.basename(pathname)
234 self.module = os.path.splitext(self.filename)[0]
235 except:
236 self.filename = pathname
237 self.module = "Unknown module"
238 self.exc_info = exc_info
239 self.exc_text = None # used to cache the traceback text
240 self.lineno = lineno
241 self.created = ct
242 self.msecs = (ct - long(ct)) * 1000
243 self.relativeCreated = (self.created - _startTime) * 1000
244 if thread:
245 self.thread = thread.get_ident()
246 self.threadName = threading.currentThread().getName()
247 else:
248 self.thread = None
249 self.threadName = None
250 if hasattr(os, 'getpid'):
251 self.process = os.getpid()
252 else:
253 self.process = None
255 def __str__(self):
256 return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
257 self.pathname, self.lineno, self.msg)
259 def getMessage(self):
261 Return the message for this LogRecord.
263 Return the message for this LogRecord after merging any user-supplied
264 arguments with the message.
266 if not hasattr(types, "UnicodeType"): #if no unicode support...
267 msg = str(self.msg)
268 else:
269 msg = self.msg
270 if type(msg) not in (types.UnicodeType, types.StringType):
271 try:
272 msg = str(self.msg)
273 except UnicodeError:
274 msg = self.msg #Defer encoding till later
275 if self.args:
276 msg = msg % self.args
277 return msg
279 def makeLogRecord(dict):
281 Make a LogRecord whose attributes are defined by the specified dictionary,
282 This function is useful for converting a logging event received over
283 a socket connection (which is sent as a dictionary) into a LogRecord
284 instance.
286 rv = LogRecord(None, None, "", 0, "", (), None)
287 rv.__dict__.update(dict)
288 return rv
290 #---------------------------------------------------------------------------
291 # Formatter classes and functions
292 #---------------------------------------------------------------------------
294 class Formatter:
296 Formatter instances are used to convert a LogRecord to text.
298 Formatters need to know how a LogRecord is constructed. They are
299 responsible for converting a LogRecord to (usually) a string which can
300 be interpreted by either a human or an external system. The base Formatter
301 allows a formatting string to be specified. If none is supplied, the
302 default value of "%s(message)\\n" is used.
304 The Formatter can be initialized with a format string which makes use of
305 knowledge of the LogRecord attributes - e.g. the default value mentioned
306 above makes use of the fact that the user's message and arguments are pre-
307 formatted into a LogRecord's message attribute. Currently, the useful
308 attributes in a LogRecord are described by:
310 %(name)s Name of the logger (logging channel)
311 %(levelno)s Numeric logging level for the message (DEBUG, INFO,
312 WARNING, ERROR, CRITICAL)
313 %(levelname)s Text logging level for the message ("DEBUG", "INFO",
314 "WARNING", "ERROR", "CRITICAL")
315 %(pathname)s Full pathname of the source file where the logging
316 call was issued (if available)
317 %(filename)s Filename portion of pathname
318 %(module)s Module (name portion of filename)
319 %(lineno)d Source line number where the logging call was issued
320 (if available)
321 %(created)f Time when the LogRecord was created (time.time()
322 return value)
323 %(asctime)s Textual time when the LogRecord was created
324 %(msecs)d Millisecond portion of the creation time
325 %(relativeCreated)d Time in milliseconds when the LogRecord was created,
326 relative to the time the logging module was loaded
327 (typically at application startup time)
328 %(thread)d Thread ID (if available)
329 %(threadName)s Thread name (if available)
330 %(process)d Process ID (if available)
331 %(message)s The result of record.getMessage(), computed just as
332 the record is emitted
335 converter = time.localtime
337 def __init__(self, fmt=None, datefmt=None):
339 Initialize the formatter with specified format strings.
341 Initialize the formatter either with the specified format string, or a
342 default as described above. Allow for specialized date formatting with
343 the optional datefmt argument (if omitted, you get the ISO8601 format).
345 if fmt:
346 self._fmt = fmt
347 else:
348 self._fmt = "%(message)s"
349 self.datefmt = datefmt
351 def formatTime(self, record, datefmt=None):
353 Return the creation time of the specified LogRecord as formatted text.
355 This method should be called from format() by a formatter which
356 wants to make use of a formatted time. This method can be overridden
357 in formatters to provide for any specific requirement, but the
358 basic behaviour is as follows: if datefmt (a string) is specified,
359 it is used with time.strftime() to format the creation time of the
360 record. Otherwise, the ISO8601 format is used. The resulting
361 string is returned. This function uses a user-configurable function
362 to convert the creation time to a tuple. By default, time.localtime()
363 is used; to change this for a particular formatter instance, set the
364 'converter' attribute to a function with the same signature as
365 time.localtime() or time.gmtime(). To change it for all formatters,
366 for example if you want all logging times to be shown in GMT,
367 set the 'converter' attribute in the Formatter class.
369 ct = self.converter(record.created)
370 if datefmt:
371 s = time.strftime(datefmt, ct)
372 else:
373 t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
374 s = "%s,%03d" % (t, record.msecs)
375 return s
377 def formatException(self, ei):
379 Format and return the specified exception information as a string.
381 This default implementation just uses
382 traceback.print_exception()
384 sio = cStringIO.StringIO()
385 traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
386 s = sio.getvalue()
387 sio.close()
388 if s[-1] == "\n":
389 s = s[:-1]
390 return s
392 def format(self, record):
394 Format the specified record as text.
396 The record's attribute dictionary is used as the operand to a
397 string formatting operation which yields the returned string.
398 Before formatting the dictionary, a couple of preparatory steps
399 are carried out. The message attribute of the record is computed
400 using LogRecord.getMessage(). If the formatting string contains
401 "%(asctime)", formatTime() is called to format the event time.
402 If there is exception information, it is formatted using
403 formatException() and appended to the message.
405 record.message = record.getMessage()
406 if string.find(self._fmt,"%(asctime)") >= 0:
407 record.asctime = self.formatTime(record, self.datefmt)
408 s = self._fmt % record.__dict__
409 if record.exc_info:
410 # Cache the traceback text to avoid converting it multiple times
411 # (it's constant anyway)
412 if not record.exc_text:
413 record.exc_text = self.formatException(record.exc_info)
414 if record.exc_text:
415 if s[-1] != "\n":
416 s = s + "\n"
417 s = s + record.exc_text
418 return s
421 # The default formatter to use when no other is specified
423 _defaultFormatter = Formatter()
425 class BufferingFormatter:
427 A formatter suitable for formatting a number of records.
429 def __init__(self, linefmt=None):
431 Optionally specify a formatter which will be used to format each
432 individual record.
434 if linefmt:
435 self.linefmt = linefmt
436 else:
437 self.linefmt = _defaultFormatter
439 def formatHeader(self, records):
441 Return the header string for the specified records.
443 return ""
445 def formatFooter(self, records):
447 Return the footer string for the specified records.
449 return ""
451 def format(self, records):
453 Format the specified records and return the result as a string.
455 rv = ""
456 if len(records) > 0:
457 rv = rv + self.formatHeader(records)
458 for record in records:
459 rv = rv + self.linefmt.format(record)
460 rv = rv + self.formatFooter(records)
461 return rv
463 #---------------------------------------------------------------------------
464 # Filter classes and functions
465 #---------------------------------------------------------------------------
467 class Filter:
469 Filter instances are used to perform arbitrary filtering of LogRecords.
471 Loggers and Handlers can optionally use Filter instances to filter
472 records as desired. The base filter class only allows events which are
473 below a certain point in the logger hierarchy. For example, a filter
474 initialized with "A.B" will allow events logged by loggers "A.B",
475 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
476 initialized with the empty string, all events are passed.
478 def __init__(self, name=''):
480 Initialize a filter.
482 Initialize with the name of the logger which, together with its
483 children, will have its events allowed through the filter. If no
484 name is specified, allow every event.
486 self.name = name
487 self.nlen = len(name)
489 def filter(self, record):
491 Determine if the specified record is to be logged.
493 Is the specified record to be logged? Returns 0 for no, nonzero for
494 yes. If deemed appropriate, the record may be modified in-place.
496 if self.nlen == 0:
497 return 1
498 elif self.name == record.name:
499 return 1
500 elif string.find(record.name, self.name, 0, self.nlen) != 0:
501 return 0
502 return (record.name[self.nlen] == ".")
504 class Filterer:
506 A base class for loggers and handlers which allows them to share
507 common code.
509 def __init__(self):
511 Initialize the list of filters to be an empty list.
513 self.filters = []
515 def addFilter(self, filter):
517 Add the specified filter to this handler.
519 if not (filter in self.filters):
520 self.filters.append(filter)
522 def removeFilter(self, filter):
524 Remove the specified filter from this handler.
526 if filter in self.filters:
527 self.filters.remove(filter)
529 def filter(self, record):
531 Determine if a record is loggable by consulting all the filters.
533 The default is to allow the record to be logged; any filter can veto
534 this and the record is then dropped. Returns a zero value if a record
535 is to be dropped, else non-zero.
537 rv = 1
538 for f in self.filters:
539 if not f.filter(record):
540 rv = 0
541 break
542 return rv
544 #---------------------------------------------------------------------------
545 # Handler classes and functions
546 #---------------------------------------------------------------------------
548 _handlers = {} #repository of handlers (for flushing when shutdown called)
549 _handlerList = [] # added to allow handlers to be removed in reverse of order initialized
551 class Handler(Filterer):
553 Handler instances dispatch logging events to specific destinations.
555 The base handler class. Acts as a placeholder which defines the Handler
556 interface. Handlers can optionally use Formatter instances to format
557 records as desired. By default, no formatter is specified; in this case,
558 the 'raw' message as determined by record.message is logged.
560 def __init__(self, level=NOTSET):
562 Initializes the instance - basically setting the formatter to None
563 and the filter list to empty.
565 Filterer.__init__(self)
566 self.level = level
567 self.formatter = None
568 #get the module data lock, as we're updating a shared structure.
569 _acquireLock()
570 try: #unlikely to raise an exception, but you never know...
571 _handlers[self] = 1
572 _handlerList.insert(0, self)
573 finally:
574 _releaseLock()
575 self.createLock()
577 def createLock(self):
579 Acquire a thread lock for serializing access to the underlying I/O.
581 if thread:
582 self.lock = threading.RLock()
583 else:
584 self.lock = None
586 def acquire(self):
588 Acquire the I/O thread lock.
590 if self.lock:
591 self.lock.acquire()
593 def release(self):
595 Release the I/O thread lock.
597 if self.lock:
598 self.lock.release()
600 def setLevel(self, level):
602 Set the logging level of this handler.
604 self.level = level
606 def format(self, record):
608 Format the specified record.
610 If a formatter is set, use it. Otherwise, use the default formatter
611 for the module.
613 if self.formatter:
614 fmt = self.formatter
615 else:
616 fmt = _defaultFormatter
617 return fmt.format(record)
619 def emit(self, record):
621 Do whatever it takes to actually log the specified logging record.
623 This version is intended to be implemented by subclasses and so
624 raises a NotImplementedError.
626 raise NotImplementedError, 'emit must be implemented '\
627 'by Handler subclasses'
629 def handle(self, record):
631 Conditionally emit the specified logging record.
633 Emission depends on filters which may have been added to the handler.
634 Wrap the actual emission of the record with acquisition/release of
635 the I/O thread lock. Returns whether the filter passed the record for
636 emission.
638 rv = self.filter(record)
639 if rv:
640 self.acquire()
641 try:
642 self.emit(record)
643 finally:
644 self.release()
645 return rv
647 def setFormatter(self, fmt):
649 Set the formatter for this handler.
651 self.formatter = fmt
653 def flush(self):
655 Ensure all logging output has been flushed.
657 This version does nothing and is intended to be implemented by
658 subclasses.
660 pass
662 def close(self):
664 Tidy up any resources used by the handler.
666 This version does removes the handler from an internal list
667 of handlers which is closed when shutdown() is called. Subclasses
668 should ensure that this gets called from overridden close()
669 methods.
671 #get the module data lock, as we're updating a shared structure.
672 _acquireLock()
673 try: #unlikely to raise an exception, but you never know...
674 del _handlers[self]
675 _handlerList.remove(self)
676 finally:
677 _releaseLock()
679 def handleError(self, record):
681 Handle errors which occur during an emit() call.
683 This method should be called from handlers when an exception is
684 encountered during an emit() call. If raiseExceptions is false,
685 exceptions get silently ignored. This is what is mostly wanted
686 for a logging system - most users will not care about errors in
687 the logging system, they are more interested in application errors.
688 You could, however, replace this with a custom handler if you wish.
689 The record which was being processed is passed in to this method.
691 if raiseExceptions:
692 ei = sys.exc_info()
693 traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
694 del ei
696 class StreamHandler(Handler):
698 A handler class which writes logging records, appropriately formatted,
699 to a stream. Note that this class does not close the stream, as
700 sys.stdout or sys.stderr may be used.
702 def __init__(self, strm=None):
704 Initialize the handler.
706 If strm is not specified, sys.stderr is used.
708 Handler.__init__(self)
709 if not strm:
710 strm = sys.stderr
711 self.stream = strm
712 self.formatter = None
714 def flush(self):
716 Flushes the stream.
718 self.stream.flush()
720 def emit(self, record):
722 Emit a record.
724 If a formatter is specified, it is used to format the record.
725 The record is then written to the stream with a trailing newline
726 [N.B. this may be removed depending on feedback]. If exception
727 information is present, it is formatted using
728 traceback.print_exception and appended to the stream.
730 try:
731 msg = self.format(record)
732 fs = "%s\n"
733 if not hasattr(types, "UnicodeType"): #if no unicode support...
734 self.stream.write(fs % msg)
735 else:
736 try:
737 self.stream.write(fs % msg)
738 except UnicodeError:
739 self.stream.write(fs % msg.encode("UTF-8"))
740 self.flush()
741 except (KeyboardInterrupt, SystemExit):
742 raise
743 except:
744 self.handleError(record)
746 class FileHandler(StreamHandler):
748 A handler class which writes formatted logging records to disk files.
750 def __init__(self, filename, mode='a', encoding=None):
752 Open the specified file and use it as the stream for logging.
754 if codecs is None:
755 encoding = None
756 if encoding is None:
757 stream = open(filename, mode)
758 else:
759 stream = codecs.open(filename, mode, encoding)
760 StreamHandler.__init__(self, stream)
761 #keep the absolute path, otherwise derived classes which use this
762 #may come a cropper when the current directory changes
763 self.baseFilename = os.path.abspath(filename)
764 self.mode = mode
766 def close(self):
768 Closes the stream.
770 self.flush()
771 self.stream.close()
772 StreamHandler.close(self)
774 #---------------------------------------------------------------------------
775 # Manager classes and functions
776 #---------------------------------------------------------------------------
778 class PlaceHolder:
780 PlaceHolder instances are used in the Manager logger hierarchy to take
781 the place of nodes for which no loggers have been defined. This class is
782 intended for internal use only and not as part of the public API.
784 def __init__(self, alogger):
786 Initialize with the specified logger being a child of this placeholder.
788 #self.loggers = [alogger]
789 self.loggerMap = { alogger : None }
791 def append(self, alogger):
793 Add the specified logger as a child of this placeholder.
795 #if alogger not in self.loggers:
796 if not self.loggerMap.has_key(alogger):
797 #self.loggers.append(alogger)
798 self.loggerMap[alogger] = None
801 # Determine which class to use when instantiating loggers.
803 _loggerClass = None
805 def setLoggerClass(klass):
807 Set the class to be used when instantiating a logger. The class should
808 define __init__() such that only a name argument is required, and the
809 __init__() should call Logger.__init__()
811 if klass != Logger:
812 if not issubclass(klass, Logger):
813 raise TypeError, "logger not derived from logging.Logger: " + \
814 klass.__name__
815 global _loggerClass
816 _loggerClass = klass
818 def getLoggerClass():
820 Return the class to be used when instantiating a logger.
823 return _loggerClass
825 class Manager:
827 There is [under normal circumstances] just one Manager instance, which
828 holds the hierarchy of loggers.
830 def __init__(self, rootnode):
832 Initialize the manager with the root node of the logger hierarchy.
834 self.root = rootnode
835 self.disable = 0
836 self.emittedNoHandlerWarning = 0
837 self.loggerDict = {}
839 def getLogger(self, name):
841 Get a logger with the specified name (channel name), creating it
842 if it doesn't yet exist. This name is a dot-separated hierarchical
843 name, such as "a", "a.b", "a.b.c" or similar.
845 If a PlaceHolder existed for the specified name [i.e. the logger
846 didn't exist but a child of it did], replace it with the created
847 logger and fix up the parent/child references which pointed to the
848 placeholder to now point to the logger.
850 rv = None
851 _acquireLock()
852 try:
853 if self.loggerDict.has_key(name):
854 rv = self.loggerDict[name]
855 if isinstance(rv, PlaceHolder):
856 ph = rv
857 rv = _loggerClass(name)
858 rv.manager = self
859 self.loggerDict[name] = rv
860 self._fixupChildren(ph, rv)
861 self._fixupParents(rv)
862 else:
863 rv = _loggerClass(name)
864 rv.manager = self
865 self.loggerDict[name] = rv
866 self._fixupParents(rv)
867 finally:
868 _releaseLock()
869 return rv
871 def _fixupParents(self, alogger):
873 Ensure that there are either loggers or placeholders all the way
874 from the specified logger to the root of the logger hierarchy.
876 name = alogger.name
877 i = string.rfind(name, ".")
878 rv = None
879 while (i > 0) and not rv:
880 substr = name[:i]
881 if not self.loggerDict.has_key(substr):
882 self.loggerDict[substr] = PlaceHolder(alogger)
883 else:
884 obj = self.loggerDict[substr]
885 if isinstance(obj, Logger):
886 rv = obj
887 else:
888 assert isinstance(obj, PlaceHolder)
889 obj.append(alogger)
890 i = string.rfind(name, ".", 0, i - 1)
891 if not rv:
892 rv = self.root
893 alogger.parent = rv
895 def _fixupChildren(self, ph, alogger):
897 Ensure that children of the placeholder ph are connected to the
898 specified logger.
900 #for c in ph.loggers:
901 for c in ph.loggerMap.keys():
902 if string.find(c.parent.name, alogger.name) <> 0:
903 alogger.parent = c.parent
904 c.parent = alogger
906 #---------------------------------------------------------------------------
907 # Logger classes and functions
908 #---------------------------------------------------------------------------
910 class Logger(Filterer):
912 Instances of the Logger class represent a single logging channel. A
913 "logging channel" indicates an area of an application. Exactly how an
914 "area" is defined is up to the application developer. Since an
915 application can have any number of areas, logging channels are identified
916 by a unique string. Application areas can be nested (e.g. an area
917 of "input processing" might include sub-areas "read CSV files", "read
918 XLS files" and "read Gnumeric files"). To cater for this natural nesting,
919 channel names are organized into a namespace hierarchy where levels are
920 separated by periods, much like the Java or Python package namespace. So
921 in the instance given above, channel names might be "input" for the upper
922 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
923 There is no arbitrary limit to the depth of nesting.
925 def __init__(self, name, level=NOTSET):
927 Initialize the logger with a name and an optional level.
929 Filterer.__init__(self)
930 self.name = name
931 self.level = level
932 self.parent = None
933 self.propagate = 1
934 self.handlers = []
935 self.disabled = 0
937 def setLevel(self, level):
939 Set the logging level of this logger.
941 self.level = level
943 def debug(self, msg, *args, **kwargs):
945 Log 'msg % args' with severity 'DEBUG'.
947 To pass exception information, use the keyword argument exc_info with
948 a true value, e.g.
950 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
952 if self.manager.disable >= DEBUG:
953 return
954 if DEBUG >= self.getEffectiveLevel():
955 apply(self._log, (DEBUG, msg, args), kwargs)
957 def info(self, msg, *args, **kwargs):
959 Log 'msg % args' with severity 'INFO'.
961 To pass exception information, use the keyword argument exc_info with
962 a true value, e.g.
964 logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
966 if self.manager.disable >= INFO:
967 return
968 if INFO >= self.getEffectiveLevel():
969 apply(self._log, (INFO, msg, args), kwargs)
971 def warning(self, msg, *args, **kwargs):
973 Log 'msg % args' with severity 'WARNING'.
975 To pass exception information, use the keyword argument exc_info with
976 a true value, e.g.
978 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
980 if self.manager.disable >= WARNING:
981 return
982 if self.isEnabledFor(WARNING):
983 apply(self._log, (WARNING, msg, args), kwargs)
985 warn = warning
987 def error(self, msg, *args, **kwargs):
989 Log 'msg % args' with severity 'ERROR'.
991 To pass exception information, use the keyword argument exc_info with
992 a true value, e.g.
994 logger.error("Houston, we have a %s", "major problem", exc_info=1)
996 if self.manager.disable >= ERROR:
997 return
998 if self.isEnabledFor(ERROR):
999 apply(self._log, (ERROR, msg, args), kwargs)
1001 def exception(self, msg, *args):
1003 Convenience method for logging an ERROR with exception information.
1005 apply(self.error, (msg,) + args, {'exc_info': 1})
1007 def critical(self, msg, *args, **kwargs):
1009 Log 'msg % args' with severity 'CRITICAL'.
1011 To pass exception information, use the keyword argument exc_info with
1012 a true value, e.g.
1014 logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
1016 if self.manager.disable >= CRITICAL:
1017 return
1018 if CRITICAL >= self.getEffectiveLevel():
1019 apply(self._log, (CRITICAL, msg, args), kwargs)
1021 fatal = critical
1023 def log(self, level, msg, *args, **kwargs):
1025 Log 'msg % args' with the integer severity 'level'.
1027 To pass exception information, use the keyword argument exc_info with
1028 a true value, e.g.
1030 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1032 if type(level) != types.IntType:
1033 if raiseExceptions:
1034 raise TypeError, "level must be an integer"
1035 else:
1036 return
1037 if self.manager.disable >= level:
1038 return
1039 if self.isEnabledFor(level):
1040 apply(self._log, (level, msg, args), kwargs)
1042 def findCaller(self):
1044 Find the stack frame of the caller so that we can note the source
1045 file name, line number and function name.
1047 f = currentframe().f_back
1048 while 1:
1049 co = f.f_code
1050 filename = os.path.normcase(co.co_filename)
1051 if filename == _srcfile:
1052 f = f.f_back
1053 continue
1054 return filename, f.f_lineno, co.co_name
1056 def makeRecord(self, name, level, fn, lno, msg, args, exc_info):
1058 A factory method which can be overridden in subclasses to create
1059 specialized LogRecords.
1061 return LogRecord(name, level, fn, lno, msg, args, exc_info)
1063 def _log(self, level, msg, args, exc_info=None):
1065 Low-level logging routine which creates a LogRecord and then calls
1066 all the handlers of this logger to handle the record.
1068 if _srcfile:
1069 fn, lno, func = self.findCaller()
1070 else:
1071 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1072 if exc_info:
1073 if type(exc_info) != types.TupleType:
1074 exc_info = sys.exc_info()
1075 record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info)
1076 self.handle(record)
1078 def handle(self, record):
1080 Call the handlers for the specified record.
1082 This method is used for unpickled records received from a socket, as
1083 well as those created locally. Logger-level filtering is applied.
1085 if (not self.disabled) and self.filter(record):
1086 self.callHandlers(record)
1088 def addHandler(self, hdlr):
1090 Add the specified handler to this logger.
1092 if not (hdlr in self.handlers):
1093 self.handlers.append(hdlr)
1095 def removeHandler(self, hdlr):
1097 Remove the specified handler from this logger.
1099 if hdlr in self.handlers:
1100 #hdlr.close()
1101 hdlr.acquire()
1102 try:
1103 self.handlers.remove(hdlr)
1104 finally:
1105 hdlr.release()
1107 def callHandlers(self, record):
1109 Pass a record to all relevant handlers.
1111 Loop through all handlers for this logger and its parents in the
1112 logger hierarchy. If no handler was found, output a one-off error
1113 message to sys.stderr. Stop searching up the hierarchy whenever a
1114 logger with the "propagate" attribute set to zero is found - that
1115 will be the last logger whose handlers are called.
1117 c = self
1118 found = 0
1119 while c:
1120 for hdlr in c.handlers:
1121 found = found + 1
1122 if record.levelno >= hdlr.level:
1123 hdlr.handle(record)
1124 if not c.propagate:
1125 c = None #break out
1126 else:
1127 c = c.parent
1128 if (found == 0) and raiseExceptions and not self.manager.emittedNoHandlerWarning:
1129 sys.stderr.write("No handlers could be found for logger"
1130 " \"%s\"\n" % self.name)
1131 self.manager.emittedNoHandlerWarning = 1
1133 def getEffectiveLevel(self):
1135 Get the effective level for this logger.
1137 Loop through this logger and its parents in the logger hierarchy,
1138 looking for a non-zero logging level. Return the first one found.
1140 logger = self
1141 while logger:
1142 if logger.level:
1143 return logger.level
1144 logger = logger.parent
1145 return NOTSET
1147 def isEnabledFor(self, level):
1149 Is this logger enabled for level 'level'?
1151 if self.manager.disable >= level:
1152 return 0
1153 return level >= self.getEffectiveLevel()
1155 class RootLogger(Logger):
1157 A root logger is not that different to any other logger, except that
1158 it must have a logging level and there is only one instance of it in
1159 the hierarchy.
1161 def __init__(self, level):
1163 Initialize the logger with the name "root".
1165 Logger.__init__(self, "root", level)
1167 _loggerClass = Logger
1169 root = RootLogger(WARNING)
1170 Logger.root = root
1171 Logger.manager = Manager(Logger.root)
1173 #---------------------------------------------------------------------------
1174 # Configuration classes and functions
1175 #---------------------------------------------------------------------------
1177 BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
1179 def basicConfig(**kwargs):
1181 Do basic configuration for the logging system.
1183 This function does nothing if the root logger already has handlers
1184 configured. It is a convenience method intended for use by simple scripts
1185 to do one-shot configuration of the logging package.
1187 The default behaviour is to create a StreamHandler which writes to
1188 sys.stderr, set a formatter using the BASIC_FORMAT format string, and
1189 add the handler to the root logger.
1191 A number of optional keyword arguments may be specified, which can alter
1192 the default behaviour.
1194 filename Specifies that a FileHandler be created, using the specified
1195 filename, rather than a StreamHandler.
1196 filemode Specifies the mode to open the file, if filename is specified
1197 (if filemode is unspecified, it defaults to 'a').
1198 format Use the specified format string for the handler.
1199 datefmt Use the specified date/time format.
1200 level Set the root logger level to the specified level.
1201 stream Use the specified stream to initialize the StreamHandler. Note
1202 that this argument is incompatible with 'filename' - if both
1203 are present, 'stream' is ignored.
1205 Note that you could specify a stream created using open(filename, mode)
1206 rather than passing the filename and mode in. However, it should be
1207 remembered that StreamHandler does not close its stream (since it may be
1208 using sys.stdout or sys.stderr), whereas FileHandler closes its stream
1209 when the handler is closed.
1211 if len(root.handlers) == 0:
1212 filename = kwargs.get("filename")
1213 if filename:
1214 mode = kwargs.get("filemode", 'a')
1215 hdlr = FileHandler(filename, mode)
1216 else:
1217 stream = kwargs.get("stream")
1218 hdlr = StreamHandler(stream)
1219 fs = kwargs.get("format", BASIC_FORMAT)
1220 dfs = kwargs.get("datefmt", None)
1221 fmt = Formatter(fs, dfs)
1222 hdlr.setFormatter(fmt)
1223 root.addHandler(hdlr)
1224 level = kwargs.get("level")
1225 if level:
1226 root.setLevel(level)
1228 #---------------------------------------------------------------------------
1229 # Utility functions at module level.
1230 # Basically delegate everything to the root logger.
1231 #---------------------------------------------------------------------------
1233 def getLogger(name=None):
1235 Return a logger with the specified name, creating it if necessary.
1237 If no name is specified, return the root logger.
1239 if name:
1240 return Logger.manager.getLogger(name)
1241 else:
1242 return root
1244 #def getRootLogger():
1245 # """
1246 # Return the root logger.
1248 # Note that getLogger('') now does the same thing, so this function is
1249 # deprecated and may disappear in the future.
1250 # """
1251 # return root
1253 def critical(msg, *args, **kwargs):
1255 Log a message with severity 'CRITICAL' on the root logger.
1257 if len(root.handlers) == 0:
1258 basicConfig()
1259 apply(root.critical, (msg,)+args, kwargs)
1261 fatal = critical
1263 def error(msg, *args, **kwargs):
1265 Log a message with severity 'ERROR' on the root logger.
1267 if len(root.handlers) == 0:
1268 basicConfig()
1269 apply(root.error, (msg,)+args, kwargs)
1271 def exception(msg, *args):
1273 Log a message with severity 'ERROR' on the root logger,
1274 with exception information.
1276 apply(error, (msg,)+args, {'exc_info': 1})
1278 def warning(msg, *args, **kwargs):
1280 Log a message with severity 'WARNING' on the root logger.
1282 if len(root.handlers) == 0:
1283 basicConfig()
1284 apply(root.warning, (msg,)+args, kwargs)
1286 warn = warning
1288 def info(msg, *args, **kwargs):
1290 Log a message with severity 'INFO' on the root logger.
1292 if len(root.handlers) == 0:
1293 basicConfig()
1294 apply(root.info, (msg,)+args, kwargs)
1296 def debug(msg, *args, **kwargs):
1298 Log a message with severity 'DEBUG' on the root logger.
1300 if len(root.handlers) == 0:
1301 basicConfig()
1302 apply(root.debug, (msg,)+args, kwargs)
1304 def log(level, msg, *args, **kwargs):
1306 Log 'msg % args' with the integer severity 'level' on the root logger.
1308 if len(root.handlers) == 0:
1309 basicConfig()
1310 apply(root.log, (level, msg)+args, kwargs)
1312 def disable(level):
1314 Disable all logging calls less severe than 'level'.
1316 root.manager.disable = level
1318 def shutdown():
1320 Perform any cleanup actions in the logging system (e.g. flushing
1321 buffers).
1323 Should be called at application exit.
1325 for h in _handlerList[:]: # was _handlers.keys():
1326 #errors might occur, for example, if files are locked
1327 #we just ignore them
1328 try:
1329 h.flush()
1330 h.close()
1331 except:
1332 pass
1334 #Let's try and shutdown automatically on application exit...
1335 try:
1336 import atexit
1337 atexit.register(shutdown)
1338 except ImportError: # for Python versions < 2.0
1339 def exithook(status, old_exit=sys.exit):
1340 try:
1341 shutdown()
1342 finally:
1343 old_exit(status)
1345 sys.exit = exithook