Change to improve speed of _fixupChildren
[python.git] / Lib / logging / __init__.py
blobc72730843e46af01e1c7e94a8f671a43c8f401a8
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__ = "production"
44 __version__ = "0.4.9.9"
45 __date__ = "06 February 2006"
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
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 args[0] and (type(args[0]) == types.DictType):
238 args = args[0]
239 self.args = args
240 self.levelname = getLevelName(level)
241 self.levelno = level
242 self.pathname = pathname
243 try:
244 self.filename = os.path.basename(pathname)
245 self.module = os.path.splitext(self.filename)[0]
246 except:
247 self.filename = pathname
248 self.module = "Unknown module"
249 self.exc_info = exc_info
250 self.exc_text = None # used to cache the traceback text
251 self.lineno = lineno
252 self.funcName = func
253 self.created = ct
254 self.msecs = (ct - long(ct)) * 1000
255 self.relativeCreated = (self.created - _startTime) * 1000
256 if logThreads and thread:
257 self.thread = thread.get_ident()
258 self.threadName = threading.currentThread().getName()
259 else:
260 self.thread = None
261 self.threadName = None
262 if logProcesses and hasattr(os, 'getpid'):
263 self.process = os.getpid()
264 else:
265 self.process = None
267 def __str__(self):
268 return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
269 self.pathname, self.lineno, self.msg)
271 def getMessage(self):
273 Return the message for this LogRecord.
275 Return the message for this LogRecord after merging any user-supplied
276 arguments with the message.
278 if not hasattr(types, "UnicodeType"): #if no unicode support...
279 msg = str(self.msg)
280 else:
281 msg = self.msg
282 if type(msg) not in (types.UnicodeType, types.StringType):
283 try:
284 msg = str(self.msg)
285 except UnicodeError:
286 msg = self.msg #Defer encoding till later
287 if self.args:
288 msg = msg % self.args
289 return msg
291 def makeLogRecord(dict):
293 Make a LogRecord whose attributes are defined by the specified dictionary,
294 This function is useful for converting a logging event received over
295 a socket connection (which is sent as a dictionary) into a LogRecord
296 instance.
298 rv = LogRecord(None, None, "", 0, "", (), None, None)
299 rv.__dict__.update(dict)
300 return rv
302 #---------------------------------------------------------------------------
303 # Formatter classes and functions
304 #---------------------------------------------------------------------------
306 class Formatter:
308 Formatter instances are used to convert a LogRecord to text.
310 Formatters need to know how a LogRecord is constructed. They are
311 responsible for converting a LogRecord to (usually) a string which can
312 be interpreted by either a human or an external system. The base Formatter
313 allows a formatting string to be specified. If none is supplied, the
314 default value of "%s(message)\\n" is used.
316 The Formatter can be initialized with a format string which makes use of
317 knowledge of the LogRecord attributes - e.g. the default value mentioned
318 above makes use of the fact that the user's message and arguments are pre-
319 formatted into a LogRecord's message attribute. Currently, the useful
320 attributes in a LogRecord are described by:
322 %(name)s Name of the logger (logging channel)
323 %(levelno)s Numeric logging level for the message (DEBUG, INFO,
324 WARNING, ERROR, CRITICAL)
325 %(levelname)s Text logging level for the message ("DEBUG", "INFO",
326 "WARNING", "ERROR", "CRITICAL")
327 %(pathname)s Full pathname of the source file where the logging
328 call was issued (if available)
329 %(filename)s Filename portion of pathname
330 %(module)s Module (name portion of filename)
331 %(lineno)d Source line number where the logging call was issued
332 (if available)
333 %(funcName)s Function name
334 %(created)f Time when the LogRecord was created (time.time()
335 return value)
336 %(asctime)s Textual time when the LogRecord was created
337 %(msecs)d Millisecond portion of the creation time
338 %(relativeCreated)d Time in milliseconds when the LogRecord was created,
339 relative to the time the logging module was loaded
340 (typically at application startup time)
341 %(thread)d Thread ID (if available)
342 %(threadName)s Thread name (if available)
343 %(process)d Process ID (if available)
344 %(message)s The result of record.getMessage(), computed just as
345 the record is emitted
348 converter = time.localtime
350 def __init__(self, fmt=None, datefmt=None):
352 Initialize the formatter with specified format strings.
354 Initialize the formatter either with the specified format string, or a
355 default as described above. Allow for specialized date formatting with
356 the optional datefmt argument (if omitted, you get the ISO8601 format).
358 if fmt:
359 self._fmt = fmt
360 else:
361 self._fmt = "%(message)s"
362 self.datefmt = datefmt
364 def formatTime(self, record, datefmt=None):
366 Return the creation time of the specified LogRecord as formatted text.
368 This method should be called from format() by a formatter which
369 wants to make use of a formatted time. This method can be overridden
370 in formatters to provide for any specific requirement, but the
371 basic behaviour is as follows: if datefmt (a string) is specified,
372 it is used with time.strftime() to format the creation time of the
373 record. Otherwise, the ISO8601 format is used. The resulting
374 string is returned. This function uses a user-configurable function
375 to convert the creation time to a tuple. By default, time.localtime()
376 is used; to change this for a particular formatter instance, set the
377 'converter' attribute to a function with the same signature as
378 time.localtime() or time.gmtime(). To change it for all formatters,
379 for example if you want all logging times to be shown in GMT,
380 set the 'converter' attribute in the Formatter class.
382 ct = self.converter(record.created)
383 if datefmt:
384 s = time.strftime(datefmt, ct)
385 else:
386 t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
387 s = "%s,%03d" % (t, record.msecs)
388 return s
390 def formatException(self, ei):
392 Format and return the specified exception information as a string.
394 This default implementation just uses
395 traceback.print_exception()
397 sio = cStringIO.StringIO()
398 traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
399 s = sio.getvalue()
400 sio.close()
401 if s[-1] == "\n":
402 s = s[:-1]
403 return s
405 def format(self, record):
407 Format the specified record as text.
409 The record's attribute dictionary is used as the operand to a
410 string formatting operation which yields the returned string.
411 Before formatting the dictionary, a couple of preparatory steps
412 are carried out. The message attribute of the record is computed
413 using LogRecord.getMessage(). If the formatting string contains
414 "%(asctime)", formatTime() is called to format the event time.
415 If there is exception information, it is formatted using
416 formatException() and appended to the message.
418 record.message = record.getMessage()
419 if string.find(self._fmt,"%(asctime)") >= 0:
420 record.asctime = self.formatTime(record, self.datefmt)
421 s = self._fmt % record.__dict__
422 if record.exc_info:
423 # Cache the traceback text to avoid converting it multiple times
424 # (it's constant anyway)
425 if not record.exc_text:
426 record.exc_text = self.formatException(record.exc_info)
427 if record.exc_text:
428 if s[-1] != "\n":
429 s = s + "\n"
430 s = s + record.exc_text
431 return s
434 # The default formatter to use when no other is specified
436 _defaultFormatter = Formatter()
438 class BufferingFormatter:
440 A formatter suitable for formatting a number of records.
442 def __init__(self, linefmt=None):
444 Optionally specify a formatter which will be used to format each
445 individual record.
447 if linefmt:
448 self.linefmt = linefmt
449 else:
450 self.linefmt = _defaultFormatter
452 def formatHeader(self, records):
454 Return the header string for the specified records.
456 return ""
458 def formatFooter(self, records):
460 Return the footer string for the specified records.
462 return ""
464 def format(self, records):
466 Format the specified records and return the result as a string.
468 rv = ""
469 if len(records) > 0:
470 rv = rv + self.formatHeader(records)
471 for record in records:
472 rv = rv + self.linefmt.format(record)
473 rv = rv + self.formatFooter(records)
474 return rv
476 #---------------------------------------------------------------------------
477 # Filter classes and functions
478 #---------------------------------------------------------------------------
480 class Filter:
482 Filter instances are used to perform arbitrary filtering of LogRecords.
484 Loggers and Handlers can optionally use Filter instances to filter
485 records as desired. The base filter class only allows events which are
486 below a certain point in the logger hierarchy. For example, a filter
487 initialized with "A.B" will allow events logged by loggers "A.B",
488 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
489 initialized with the empty string, all events are passed.
491 def __init__(self, name=''):
493 Initialize a filter.
495 Initialize with the name of the logger which, together with its
496 children, will have its events allowed through the filter. If no
497 name is specified, allow every event.
499 self.name = name
500 self.nlen = len(name)
502 def filter(self, record):
504 Determine if the specified record is to be logged.
506 Is the specified record to be logged? Returns 0 for no, nonzero for
507 yes. If deemed appropriate, the record may be modified in-place.
509 if self.nlen == 0:
510 return 1
511 elif self.name == record.name:
512 return 1
513 elif string.find(record.name, self.name, 0, self.nlen) != 0:
514 return 0
515 return (record.name[self.nlen] == ".")
517 class Filterer:
519 A base class for loggers and handlers which allows them to share
520 common code.
522 def __init__(self):
524 Initialize the list of filters to be an empty list.
526 self.filters = []
528 def addFilter(self, filter):
530 Add the specified filter to this handler.
532 if not (filter in self.filters):
533 self.filters.append(filter)
535 def removeFilter(self, filter):
537 Remove the specified filter from this handler.
539 if filter in self.filters:
540 self.filters.remove(filter)
542 def filter(self, record):
544 Determine if a record is loggable by consulting all the filters.
546 The default is to allow the record to be logged; any filter can veto
547 this and the record is then dropped. Returns a zero value if a record
548 is to be dropped, else non-zero.
550 rv = 1
551 for f in self.filters:
552 if not f.filter(record):
553 rv = 0
554 break
555 return rv
557 #---------------------------------------------------------------------------
558 # Handler classes and functions
559 #---------------------------------------------------------------------------
561 _handlers = {} #repository of handlers (for flushing when shutdown called)
562 _handlerList = [] # added to allow handlers to be removed in reverse of order initialized
564 class Handler(Filterer):
566 Handler instances dispatch logging events to specific destinations.
568 The base handler class. Acts as a placeholder which defines the Handler
569 interface. Handlers can optionally use Formatter instances to format
570 records as desired. By default, no formatter is specified; in this case,
571 the 'raw' message as determined by record.message is logged.
573 def __init__(self, level=NOTSET):
575 Initializes the instance - basically setting the formatter to None
576 and the filter list to empty.
578 Filterer.__init__(self)
579 self.level = level
580 self.formatter = None
581 #get the module data lock, as we're updating a shared structure.
582 _acquireLock()
583 try: #unlikely to raise an exception, but you never know...
584 _handlers[self] = 1
585 _handlerList.insert(0, self)
586 finally:
587 _releaseLock()
588 self.createLock()
590 def createLock(self):
592 Acquire a thread lock for serializing access to the underlying I/O.
594 if thread:
595 self.lock = threading.RLock()
596 else:
597 self.lock = None
599 def acquire(self):
601 Acquire the I/O thread lock.
603 if self.lock:
604 self.lock.acquire()
606 def release(self):
608 Release the I/O thread lock.
610 if self.lock:
611 self.lock.release()
613 def setLevel(self, level):
615 Set the logging level of this handler.
617 self.level = level
619 def format(self, record):
621 Format the specified record.
623 If a formatter is set, use it. Otherwise, use the default formatter
624 for the module.
626 if self.formatter:
627 fmt = self.formatter
628 else:
629 fmt = _defaultFormatter
630 return fmt.format(record)
632 def emit(self, record):
634 Do whatever it takes to actually log the specified logging record.
636 This version is intended to be implemented by subclasses and so
637 raises a NotImplementedError.
639 raise NotImplementedError, 'emit must be implemented '\
640 'by Handler subclasses'
642 def handle(self, record):
644 Conditionally emit the specified logging record.
646 Emission depends on filters which may have been added to the handler.
647 Wrap the actual emission of the record with acquisition/release of
648 the I/O thread lock. Returns whether the filter passed the record for
649 emission.
651 rv = self.filter(record)
652 if rv:
653 self.acquire()
654 try:
655 self.emit(record)
656 finally:
657 self.release()
658 return rv
660 def setFormatter(self, fmt):
662 Set the formatter for this handler.
664 self.formatter = fmt
666 def flush(self):
668 Ensure all logging output has been flushed.
670 This version does nothing and is intended to be implemented by
671 subclasses.
673 pass
675 def close(self):
677 Tidy up any resources used by the handler.
679 This version does removes the handler from an internal list
680 of handlers which is closed when shutdown() is called. Subclasses
681 should ensure that this gets called from overridden close()
682 methods.
684 #get the module data lock, as we're updating a shared structure.
685 _acquireLock()
686 try: #unlikely to raise an exception, but you never know...
687 del _handlers[self]
688 _handlerList.remove(self)
689 finally:
690 _releaseLock()
692 def handleError(self, record):
694 Handle errors which occur during an emit() call.
696 This method should be called from handlers when an exception is
697 encountered during an emit() call. If raiseExceptions is false,
698 exceptions get silently ignored. This is what is mostly wanted
699 for a logging system - most users will not care about errors in
700 the logging system, they are more interested in application errors.
701 You could, however, replace this with a custom handler if you wish.
702 The record which was being processed is passed in to this method.
704 if raiseExceptions:
705 ei = sys.exc_info()
706 traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
707 del ei
709 class StreamHandler(Handler):
711 A handler class which writes logging records, appropriately formatted,
712 to a stream. Note that this class does not close the stream, as
713 sys.stdout or sys.stderr may be used.
715 def __init__(self, strm=None):
717 Initialize the handler.
719 If strm is not specified, sys.stderr is used.
721 Handler.__init__(self)
722 if strm is None:
723 strm = sys.stderr
724 self.stream = strm
725 self.formatter = None
727 def flush(self):
729 Flushes the stream.
731 self.stream.flush()
733 def emit(self, record):
735 Emit a record.
737 If a formatter is specified, it is used to format the record.
738 The record is then written to the stream with a trailing newline
739 [N.B. this may be removed depending on feedback]. If exception
740 information is present, it is formatted using
741 traceback.print_exception and appended to the stream.
743 try:
744 msg = self.format(record)
745 fs = "%s\n"
746 if not hasattr(types, "UnicodeType"): #if no unicode support...
747 self.stream.write(fs % msg)
748 else:
749 try:
750 self.stream.write(fs % msg)
751 except UnicodeError:
752 self.stream.write(fs % msg.encode("UTF-8"))
753 self.flush()
754 except (KeyboardInterrupt, SystemExit):
755 raise
756 except:
757 self.handleError(record)
759 class FileHandler(StreamHandler):
761 A handler class which writes formatted logging records to disk files.
763 def __init__(self, filename, mode='a', encoding=None):
765 Open the specified file and use it as the stream for logging.
767 if codecs is None:
768 encoding = None
769 if encoding is None:
770 stream = open(filename, mode)
771 else:
772 stream = codecs.open(filename, mode, encoding)
773 StreamHandler.__init__(self, stream)
774 #keep the absolute path, otherwise derived classes which use this
775 #may come a cropper when the current directory changes
776 self.baseFilename = os.path.abspath(filename)
777 self.mode = mode
779 def close(self):
781 Closes the stream.
783 self.flush()
784 self.stream.close()
785 StreamHandler.close(self)
787 #---------------------------------------------------------------------------
788 # Manager classes and functions
789 #---------------------------------------------------------------------------
791 class PlaceHolder:
793 PlaceHolder instances are used in the Manager logger hierarchy to take
794 the place of nodes for which no loggers have been defined. This class is
795 intended for internal use only and not as part of the public API.
797 def __init__(self, alogger):
799 Initialize with the specified logger being a child of this placeholder.
801 #self.loggers = [alogger]
802 self.loggerMap = { alogger : None }
804 def append(self, alogger):
806 Add the specified logger as a child of this placeholder.
808 #if alogger not in self.loggers:
809 if not self.loggerMap.has_key(alogger):
810 #self.loggers.append(alogger)
811 self.loggerMap[alogger] = None
814 # Determine which class to use when instantiating loggers.
816 _loggerClass = None
818 def setLoggerClass(klass):
820 Set the class to be used when instantiating a logger. The class should
821 define __init__() such that only a name argument is required, and the
822 __init__() should call Logger.__init__()
824 if klass != Logger:
825 if not issubclass(klass, Logger):
826 raise TypeError, "logger not derived from logging.Logger: " + \
827 klass.__name__
828 global _loggerClass
829 _loggerClass = klass
831 def getLoggerClass():
833 Return the class to be used when instantiating a logger.
836 return _loggerClass
838 class Manager:
840 There is [under normal circumstances] just one Manager instance, which
841 holds the hierarchy of loggers.
843 def __init__(self, rootnode):
845 Initialize the manager with the root node of the logger hierarchy.
847 self.root = rootnode
848 self.disable = 0
849 self.emittedNoHandlerWarning = 0
850 self.loggerDict = {}
852 def getLogger(self, name):
854 Get a logger with the specified name (channel name), creating it
855 if it doesn't yet exist. This name is a dot-separated hierarchical
856 name, such as "a", "a.b", "a.b.c" or similar.
858 If a PlaceHolder existed for the specified name [i.e. the logger
859 didn't exist but a child of it did], replace it with the created
860 logger and fix up the parent/child references which pointed to the
861 placeholder to now point to the logger.
863 rv = None
864 _acquireLock()
865 try:
866 if self.loggerDict.has_key(name):
867 rv = self.loggerDict[name]
868 if isinstance(rv, PlaceHolder):
869 ph = rv
870 rv = _loggerClass(name)
871 rv.manager = self
872 self.loggerDict[name] = rv
873 self._fixupChildren(ph, rv)
874 self._fixupParents(rv)
875 else:
876 rv = _loggerClass(name)
877 rv.manager = self
878 self.loggerDict[name] = rv
879 self._fixupParents(rv)
880 finally:
881 _releaseLock()
882 return rv
884 def _fixupParents(self, alogger):
886 Ensure that there are either loggers or placeholders all the way
887 from the specified logger to the root of the logger hierarchy.
889 name = alogger.name
890 i = string.rfind(name, ".")
891 rv = None
892 while (i > 0) and not rv:
893 substr = name[:i]
894 if not self.loggerDict.has_key(substr):
895 self.loggerDict[substr] = PlaceHolder(alogger)
896 else:
897 obj = self.loggerDict[substr]
898 if isinstance(obj, Logger):
899 rv = obj
900 else:
901 assert isinstance(obj, PlaceHolder)
902 obj.append(alogger)
903 i = string.rfind(name, ".", 0, i - 1)
904 if not rv:
905 rv = self.root
906 alogger.parent = rv
908 def _fixupChildren(self, ph, alogger):
910 Ensure that children of the placeholder ph are connected to the
911 specified logger.
913 name = alogger.name
914 namelen = len(name)
915 for c in ph.loggerMap.keys():
916 #The if means ... if not c.parent.name.startswith(nm)
917 #if string.find(c.parent.name, nm) <> 0:
918 if c.parent.name[:namelen] != name:
919 alogger.parent = c.parent
920 c.parent = alogger
922 #---------------------------------------------------------------------------
923 # Logger classes and functions
924 #---------------------------------------------------------------------------
926 class Logger(Filterer):
928 Instances of the Logger class represent a single logging channel. A
929 "logging channel" indicates an area of an application. Exactly how an
930 "area" is defined is up to the application developer. Since an
931 application can have any number of areas, logging channels are identified
932 by a unique string. Application areas can be nested (e.g. an area
933 of "input processing" might include sub-areas "read CSV files", "read
934 XLS files" and "read Gnumeric files"). To cater for this natural nesting,
935 channel names are organized into a namespace hierarchy where levels are
936 separated by periods, much like the Java or Python package namespace. So
937 in the instance given above, channel names might be "input" for the upper
938 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
939 There is no arbitrary limit to the depth of nesting.
941 def __init__(self, name, level=NOTSET):
943 Initialize the logger with a name and an optional level.
945 Filterer.__init__(self)
946 self.name = name
947 self.level = level
948 self.parent = None
949 self.propagate = 1
950 self.handlers = []
951 self.disabled = 0
953 def setLevel(self, level):
955 Set the logging level of this logger.
957 self.level = level
959 def debug(self, msg, *args, **kwargs):
961 Log 'msg % args' with severity 'DEBUG'.
963 To pass exception information, use the keyword argument exc_info with
964 a true value, e.g.
966 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
968 if self.manager.disable >= DEBUG:
969 return
970 if DEBUG >= self.getEffectiveLevel():
971 apply(self._log, (DEBUG, msg, args), kwargs)
973 def info(self, msg, *args, **kwargs):
975 Log 'msg % args' with severity 'INFO'.
977 To pass exception information, use the keyword argument exc_info with
978 a true value, e.g.
980 logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
982 if self.manager.disable >= INFO:
983 return
984 if INFO >= self.getEffectiveLevel():
985 apply(self._log, (INFO, msg, args), kwargs)
987 def warning(self, msg, *args, **kwargs):
989 Log 'msg % args' with severity 'WARNING'.
991 To pass exception information, use the keyword argument exc_info with
992 a true value, e.g.
994 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
996 if self.manager.disable >= WARNING:
997 return
998 if self.isEnabledFor(WARNING):
999 apply(self._log, (WARNING, msg, args), kwargs)
1001 warn = warning
1003 def error(self, msg, *args, **kwargs):
1005 Log 'msg % args' with severity 'ERROR'.
1007 To pass exception information, use the keyword argument exc_info with
1008 a true value, e.g.
1010 logger.error("Houston, we have a %s", "major problem", exc_info=1)
1012 if self.manager.disable >= ERROR:
1013 return
1014 if self.isEnabledFor(ERROR):
1015 apply(self._log, (ERROR, msg, args), kwargs)
1017 def exception(self, msg, *args):
1019 Convenience method for logging an ERROR with exception information.
1021 apply(self.error, (msg,) + args, {'exc_info': 1})
1023 def critical(self, msg, *args, **kwargs):
1025 Log 'msg % args' with severity 'CRITICAL'.
1027 To pass exception information, use the keyword argument exc_info with
1028 a true value, e.g.
1030 logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
1032 if self.manager.disable >= CRITICAL:
1033 return
1034 if CRITICAL >= self.getEffectiveLevel():
1035 apply(self._log, (CRITICAL, msg, args), kwargs)
1037 fatal = critical
1039 def log(self, level, msg, *args, **kwargs):
1041 Log 'msg % args' with the integer severity 'level'.
1043 To pass exception information, use the keyword argument exc_info with
1044 a true value, e.g.
1046 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1048 if type(level) != types.IntType:
1049 if raiseExceptions:
1050 raise TypeError, "level must be an integer"
1051 else:
1052 return
1053 if self.manager.disable >= level:
1054 return
1055 if self.isEnabledFor(level):
1056 apply(self._log, (level, msg, args), kwargs)
1058 def findCaller(self):
1060 Find the stack frame of the caller so that we can note the source
1061 file name, line number and function name.
1063 f = currentframe().f_back
1064 rv = "(unknown file)", 0, "(unknown function)"
1065 while hasattr(f, "f_code"):
1066 co = f.f_code
1067 filename = os.path.normcase(co.co_filename)
1068 if filename == _srcfile:
1069 f = f.f_back
1070 continue
1071 rv = (filename, f.f_lineno, co.co_name)
1072 break
1073 return rv
1075 def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None):
1077 A factory method which can be overridden in subclasses to create
1078 specialized LogRecords.
1080 rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func)
1081 if extra:
1082 for key in extra:
1083 if (key in ["message", "asctime"]) or (key in rv.__dict__):
1084 raise KeyError("Attempt to overwrite %r in LogRecord" % key)
1085 rv.__dict__[key] = extra[key]
1086 return rv
1088 def _log(self, level, msg, args, exc_info=None, extra=None):
1090 Low-level logging routine which creates a LogRecord and then calls
1091 all the handlers of this logger to handle the record.
1093 if _srcfile:
1094 fn, lno, func = self.findCaller()
1095 else:
1096 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1097 if exc_info:
1098 if type(exc_info) != types.TupleType:
1099 exc_info = sys.exc_info()
1100 record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra)
1101 self.handle(record)
1103 def handle(self, record):
1105 Call the handlers for the specified record.
1107 This method is used for unpickled records received from a socket, as
1108 well as those created locally. Logger-level filtering is applied.
1110 if (not self.disabled) and self.filter(record):
1111 self.callHandlers(record)
1113 def addHandler(self, hdlr):
1115 Add the specified handler to this logger.
1117 if not (hdlr in self.handlers):
1118 self.handlers.append(hdlr)
1120 def removeHandler(self, hdlr):
1122 Remove the specified handler from this logger.
1124 if hdlr in self.handlers:
1125 #hdlr.close()
1126 hdlr.acquire()
1127 try:
1128 self.handlers.remove(hdlr)
1129 finally:
1130 hdlr.release()
1132 def callHandlers(self, record):
1134 Pass a record to all relevant handlers.
1136 Loop through all handlers for this logger and its parents in the
1137 logger hierarchy. If no handler was found, output a one-off error
1138 message to sys.stderr. Stop searching up the hierarchy whenever a
1139 logger with the "propagate" attribute set to zero is found - that
1140 will be the last logger whose handlers are called.
1142 c = self
1143 found = 0
1144 while c:
1145 for hdlr in c.handlers:
1146 found = found + 1
1147 if record.levelno >= hdlr.level:
1148 hdlr.handle(record)
1149 if not c.propagate:
1150 c = None #break out
1151 else:
1152 c = c.parent
1153 if (found == 0) and raiseExceptions and not self.manager.emittedNoHandlerWarning:
1154 sys.stderr.write("No handlers could be found for logger"
1155 " \"%s\"\n" % self.name)
1156 self.manager.emittedNoHandlerWarning = 1
1158 def getEffectiveLevel(self):
1160 Get the effective level for this logger.
1162 Loop through this logger and its parents in the logger hierarchy,
1163 looking for a non-zero logging level. Return the first one found.
1165 logger = self
1166 while logger:
1167 if logger.level:
1168 return logger.level
1169 logger = logger.parent
1170 return NOTSET
1172 def isEnabledFor(self, level):
1174 Is this logger enabled for level 'level'?
1176 if self.manager.disable >= level:
1177 return 0
1178 return level >= self.getEffectiveLevel()
1180 class RootLogger(Logger):
1182 A root logger is not that different to any other logger, except that
1183 it must have a logging level and there is only one instance of it in
1184 the hierarchy.
1186 def __init__(self, level):
1188 Initialize the logger with the name "root".
1190 Logger.__init__(self, "root", level)
1192 _loggerClass = Logger
1194 root = RootLogger(WARNING)
1195 Logger.root = root
1196 Logger.manager = Manager(Logger.root)
1198 #---------------------------------------------------------------------------
1199 # Configuration classes and functions
1200 #---------------------------------------------------------------------------
1202 BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
1204 def basicConfig(**kwargs):
1206 Do basic configuration for the logging system.
1208 This function does nothing if the root logger already has handlers
1209 configured. It is a convenience method intended for use by simple scripts
1210 to do one-shot configuration of the logging package.
1212 The default behaviour is to create a StreamHandler which writes to
1213 sys.stderr, set a formatter using the BASIC_FORMAT format string, and
1214 add the handler to the root logger.
1216 A number of optional keyword arguments may be specified, which can alter
1217 the default behaviour.
1219 filename Specifies that a FileHandler be created, using the specified
1220 filename, rather than a StreamHandler.
1221 filemode Specifies the mode to open the file, if filename is specified
1222 (if filemode is unspecified, it defaults to 'a').
1223 format Use the specified format string for the handler.
1224 datefmt Use the specified date/time format.
1225 level Set the root logger level to the specified level.
1226 stream Use the specified stream to initialize the StreamHandler. Note
1227 that this argument is incompatible with 'filename' - if both
1228 are present, 'stream' is ignored.
1230 Note that you could specify a stream created using open(filename, mode)
1231 rather than passing the filename and mode in. However, it should be
1232 remembered that StreamHandler does not close its stream (since it may be
1233 using sys.stdout or sys.stderr), whereas FileHandler closes its stream
1234 when the handler is closed.
1236 if len(root.handlers) == 0:
1237 filename = kwargs.get("filename")
1238 if filename:
1239 mode = kwargs.get("filemode", 'a')
1240 hdlr = FileHandler(filename, mode)
1241 else:
1242 stream = kwargs.get("stream")
1243 hdlr = StreamHandler(stream)
1244 fs = kwargs.get("format", BASIC_FORMAT)
1245 dfs = kwargs.get("datefmt", None)
1246 fmt = Formatter(fs, dfs)
1247 hdlr.setFormatter(fmt)
1248 root.addHandler(hdlr)
1249 level = kwargs.get("level")
1250 if level:
1251 root.setLevel(level)
1253 #---------------------------------------------------------------------------
1254 # Utility functions at module level.
1255 # Basically delegate everything to the root logger.
1256 #---------------------------------------------------------------------------
1258 def getLogger(name=None):
1260 Return a logger with the specified name, creating it if necessary.
1262 If no name is specified, return the root logger.
1264 if name:
1265 return Logger.manager.getLogger(name)
1266 else:
1267 return root
1269 #def getRootLogger():
1270 # """
1271 # Return the root logger.
1273 # Note that getLogger('') now does the same thing, so this function is
1274 # deprecated and may disappear in the future.
1275 # """
1276 # return root
1278 def critical(msg, *args, **kwargs):
1280 Log a message with severity 'CRITICAL' on the root logger.
1282 if len(root.handlers) == 0:
1283 basicConfig()
1284 apply(root.critical, (msg,)+args, kwargs)
1286 fatal = critical
1288 def error(msg, *args, **kwargs):
1290 Log a message with severity 'ERROR' on the root logger.
1292 if len(root.handlers) == 0:
1293 basicConfig()
1294 apply(root.error, (msg,)+args, kwargs)
1296 def exception(msg, *args):
1298 Log a message with severity 'ERROR' on the root logger,
1299 with exception information.
1301 apply(error, (msg,)+args, {'exc_info': 1})
1303 def warning(msg, *args, **kwargs):
1305 Log a message with severity 'WARNING' on the root logger.
1307 if len(root.handlers) == 0:
1308 basicConfig()
1309 apply(root.warning, (msg,)+args, kwargs)
1311 warn = warning
1313 def info(msg, *args, **kwargs):
1315 Log a message with severity 'INFO' on the root logger.
1317 if len(root.handlers) == 0:
1318 basicConfig()
1319 apply(root.info, (msg,)+args, kwargs)
1321 def debug(msg, *args, **kwargs):
1323 Log a message with severity 'DEBUG' on the root logger.
1325 if len(root.handlers) == 0:
1326 basicConfig()
1327 apply(root.debug, (msg,)+args, kwargs)
1329 def log(level, msg, *args, **kwargs):
1331 Log 'msg % args' with the integer severity 'level' on the root logger.
1333 if len(root.handlers) == 0:
1334 basicConfig()
1335 apply(root.log, (level, msg)+args, kwargs)
1337 def disable(level):
1339 Disable all logging calls less severe than 'level'.
1341 root.manager.disable = level
1343 def shutdown(handlerList=_handlerList):
1345 Perform any cleanup actions in the logging system (e.g. flushing
1346 buffers).
1348 Should be called at application exit.
1350 for h in handlerList[:]:
1351 #errors might occur, for example, if files are locked
1352 #we just ignore them if raiseExceptions is not set
1353 try:
1354 h.flush()
1355 h.close()
1356 except:
1357 if raiseExceptions:
1358 raise
1359 #else, swallow
1361 #Let's try and shutdown automatically on application exit...
1362 try:
1363 import atexit
1364 atexit.register(shutdown)
1365 except ImportError: # for Python versions < 2.0
1366 def exithook(status, old_exit=sys.exit):
1367 try:
1368 shutdown()
1369 finally:
1370 old_exit(status)
1372 sys.exit = exithook