Require implementations for warnings.showwarning() support the 'line' argument.
[python.git] / Lib / logging / __init__.py
blobe7eb51df3bdc280b9fb0400c886ff25ffc6679df
1 # Copyright 2001-2009 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 Copyright (C) 2001-2009 Vinay Sajip. All Rights Reserved.
23 To use, simply 'import logging' and log away!
24 """
26 __all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
27 'FATAL', 'FileHandler', 'Filter', 'Filterer', 'Formatter', 'Handler',
28 'INFO', 'LogRecord', 'Logger', 'Manager', 'NOTSET', 'PlaceHolder',
29 'RootLogger', 'StreamHandler', 'WARN', 'WARNING']
31 import sys, os, types, time, string, cStringIO, traceback, warnings
33 try:
34 import codecs
35 except ImportError:
36 codecs = None
38 try:
39 import thread
40 import threading
41 except ImportError:
42 thread = None
44 __author__ = "Vinay Sajip <vinay_sajip@red-dove.com>"
45 __status__ = "production"
46 __version__ = "0.5.0.7"
47 __date__ = "20 January 2009"
49 #---------------------------------------------------------------------------
50 # Miscellaneous module data
51 #---------------------------------------------------------------------------
54 # _srcfile is used when walking the stack to check when we've got the first
55 # caller stack frame.
57 if hasattr(sys, 'frozen'): #support for py2exe
58 _srcfile = "logging%s__init__%s" % (os.sep, __file__[-4:])
59 elif string.lower(__file__[-4:]) in ['.pyc', '.pyo']:
60 _srcfile = __file__[:-4] + '.py'
61 else:
62 _srcfile = __file__
63 _srcfile = os.path.normcase(_srcfile)
65 # next bit filched from 1.5.2's inspect.py
66 def currentframe():
67 """Return the frame object for the caller's stack frame."""
68 try:
69 raise Exception
70 except:
71 return sys.exc_traceback.tb_frame.f_back
73 if hasattr(sys, '_getframe'): currentframe = lambda: sys._getframe(3)
74 # done filching
76 # _srcfile is only used in conjunction with sys._getframe().
77 # To provide compatibility with older versions of Python, set _srcfile
78 # to None if _getframe() is not available; this value will prevent
79 # findCaller() from being called.
80 #if not hasattr(sys, "_getframe"):
81 # _srcfile = None
84 #_startTime is used as the base when calculating the relative time of events
86 _startTime = time.time()
89 #raiseExceptions is used to see if exceptions during handling should be
90 #propagated
92 raiseExceptions = 1
95 # If you don't want threading information in the log, set this to zero
97 logThreads = 1
100 # If you don't want multiprocessing information in the log, set this to zero
102 logMultiprocessing = 1
105 # If you don't want process information in the log, set this to zero
107 logProcesses = 1
109 #---------------------------------------------------------------------------
110 # Level related stuff
111 #---------------------------------------------------------------------------
113 # Default levels and level names, these can be replaced with any positive set
114 # of values having corresponding names. There is a pseudo-level, NOTSET, which
115 # is only really there as a lower limit for user-defined levels. Handlers and
116 # loggers are initialized with NOTSET so that they will log all messages, even
117 # at user-defined levels.
120 CRITICAL = 50
121 FATAL = CRITICAL
122 ERROR = 40
123 WARNING = 30
124 WARN = WARNING
125 INFO = 20
126 DEBUG = 10
127 NOTSET = 0
129 _levelNames = {
130 CRITICAL : 'CRITICAL',
131 ERROR : 'ERROR',
132 WARNING : 'WARNING',
133 INFO : 'INFO',
134 DEBUG : 'DEBUG',
135 NOTSET : 'NOTSET',
136 'CRITICAL' : CRITICAL,
137 'ERROR' : ERROR,
138 'WARN' : WARNING,
139 'WARNING' : WARNING,
140 'INFO' : INFO,
141 'DEBUG' : DEBUG,
142 'NOTSET' : NOTSET,
145 def getLevelName(level):
147 Return the textual representation of logging level 'level'.
149 If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
150 INFO, DEBUG) then you get the corresponding string. If you have
151 associated levels with names using addLevelName then the name you have
152 associated with 'level' is returned.
154 If a numeric value corresponding to one of the defined levels is passed
155 in, the corresponding string representation is returned.
157 Otherwise, the string "Level %s" % level is returned.
159 return _levelNames.get(level, ("Level %s" % level))
161 def addLevelName(level, levelName):
163 Associate 'levelName' with 'level'.
165 This is used when converting levels to text during message formatting.
167 _acquireLock()
168 try: #unlikely to cause an exception, but you never know...
169 _levelNames[level] = levelName
170 _levelNames[levelName] = level
171 finally:
172 _releaseLock()
174 #---------------------------------------------------------------------------
175 # Thread-related stuff
176 #---------------------------------------------------------------------------
179 #_lock is used to serialize access to shared data structures in this module.
180 #This needs to be an RLock because fileConfig() creates Handlers and so
181 #might arbitrary user threads. Since Handler.__init__() updates the shared
182 #dictionary _handlers, it needs to acquire the lock. But if configuring,
183 #the lock would already have been acquired - so we need an RLock.
184 #The same argument applies to Loggers and Manager.loggerDict.
186 _lock = None
188 def _acquireLock():
190 Acquire the module-level lock for serializing access to shared data.
192 This should be released with _releaseLock().
194 global _lock
195 if (not _lock) and thread:
196 _lock = threading.RLock()
197 if _lock:
198 _lock.acquire()
200 def _releaseLock():
202 Release the module-level lock acquired by calling _acquireLock().
204 if _lock:
205 _lock.release()
207 #---------------------------------------------------------------------------
208 # The logging record
209 #---------------------------------------------------------------------------
211 class LogRecord:
213 A LogRecord instance represents an event being logged.
215 LogRecord instances are created every time something is logged. They
216 contain all the information pertinent to the event being logged. The
217 main information passed in is in msg and args, which are combined
218 using str(msg) % args to create the message field of the record. The
219 record also includes information such as when the record was created,
220 the source line where the logging call was made, and any exception
221 information to be logged.
223 def __init__(self, name, level, pathname, lineno,
224 msg, args, exc_info, func=None):
226 Initialize a logging record with interesting information.
228 ct = time.time()
229 self.name = name
230 self.msg = msg
232 # The following statement allows passing of a dictionary as a sole
233 # argument, so that you can do something like
234 # logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2})
235 # Suggested by Stefan Behnel.
236 # Note that without the test for args[0], we get a problem because
237 # during formatting, we test to see if the arg is present using
238 # 'if self.args:'. If the event being logged is e.g. 'Value is %d'
239 # and if the passed arg fails 'if self.args:' then no formatting
240 # is done. For example, logger.warn('Value is %d', 0) would log
241 # 'Value is %d' instead of 'Value is 0'.
242 # For the use case of passing a dictionary, this should not be a
243 # problem.
244 if args and len(args) == 1 and (
245 type(args[0]) == types.DictType
246 ) and args[0]:
247 args = args[0]
248 self.args = args
249 self.levelname = getLevelName(level)
250 self.levelno = level
251 self.pathname = pathname
252 try:
253 self.filename = os.path.basename(pathname)
254 self.module = os.path.splitext(self.filename)[0]
255 except (TypeError, ValueError, AttributeError):
256 self.filename = pathname
257 self.module = "Unknown module"
258 self.exc_info = exc_info
259 self.exc_text = None # used to cache the traceback text
260 self.lineno = lineno
261 self.funcName = func
262 self.created = ct
263 self.msecs = (ct - long(ct)) * 1000
264 self.relativeCreated = (self.created - _startTime) * 1000
265 if logThreads and thread:
266 self.thread = thread.get_ident()
267 self.threadName = threading.current_thread().name
268 else:
269 self.thread = None
270 self.threadName = None
271 if logMultiprocessing:
272 from multiprocessing import current_process
273 self.processName = current_process().name
274 else:
275 self.processName = None
276 if logProcesses and hasattr(os, 'getpid'):
277 self.process = os.getpid()
278 else:
279 self.process = None
281 def __str__(self):
282 return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
283 self.pathname, self.lineno, self.msg)
285 def getMessage(self):
287 Return the message for this LogRecord.
289 Return the message for this LogRecord after merging any user-supplied
290 arguments with the message.
292 if not hasattr(types, "UnicodeType"): #if no unicode support...
293 msg = str(self.msg)
294 else:
295 msg = self.msg
296 if type(msg) not in (types.UnicodeType, types.StringType):
297 try:
298 msg = str(self.msg)
299 except UnicodeError:
300 msg = self.msg #Defer encoding till later
301 if self.args:
302 msg = msg % self.args
303 return msg
305 def makeLogRecord(dict):
307 Make a LogRecord whose attributes are defined by the specified dictionary,
308 This function is useful for converting a logging event received over
309 a socket connection (which is sent as a dictionary) into a LogRecord
310 instance.
312 rv = LogRecord(None, None, "", 0, "", (), None, None)
313 rv.__dict__.update(dict)
314 return rv
316 #---------------------------------------------------------------------------
317 # Formatter classes and functions
318 #---------------------------------------------------------------------------
320 class Formatter:
322 Formatter instances are used to convert a LogRecord to text.
324 Formatters need to know how a LogRecord is constructed. They are
325 responsible for converting a LogRecord to (usually) a string which can
326 be interpreted by either a human or an external system. The base Formatter
327 allows a formatting string to be specified. If none is supplied, the
328 default value of "%s(message)\\n" is used.
330 The Formatter can be initialized with a format string which makes use of
331 knowledge of the LogRecord attributes - e.g. the default value mentioned
332 above makes use of the fact that the user's message and arguments are pre-
333 formatted into a LogRecord's message attribute. Currently, the useful
334 attributes in a LogRecord are described by:
336 %(name)s Name of the logger (logging channel)
337 %(levelno)s Numeric logging level for the message (DEBUG, INFO,
338 WARNING, ERROR, CRITICAL)
339 %(levelname)s Text logging level for the message ("DEBUG", "INFO",
340 "WARNING", "ERROR", "CRITICAL")
341 %(pathname)s Full pathname of the source file where the logging
342 call was issued (if available)
343 %(filename)s Filename portion of pathname
344 %(module)s Module (name portion of filename)
345 %(lineno)d Source line number where the logging call was issued
346 (if available)
347 %(funcName)s Function name
348 %(created)f Time when the LogRecord was created (time.time()
349 return value)
350 %(asctime)s Textual time when the LogRecord was created
351 %(msecs)d Millisecond portion of the creation time
352 %(relativeCreated)d Time in milliseconds when the LogRecord was created,
353 relative to the time the logging module was loaded
354 (typically at application startup time)
355 %(thread)d Thread ID (if available)
356 %(threadName)s Thread name (if available)
357 %(process)d Process ID (if available)
358 %(message)s The result of record.getMessage(), computed just as
359 the record is emitted
362 converter = time.localtime
364 def __init__(self, fmt=None, datefmt=None):
366 Initialize the formatter with specified format strings.
368 Initialize the formatter either with the specified format string, or a
369 default as described above. Allow for specialized date formatting with
370 the optional datefmt argument (if omitted, you get the ISO8601 format).
372 if fmt:
373 self._fmt = fmt
374 else:
375 self._fmt = "%(message)s"
376 self.datefmt = datefmt
378 def formatTime(self, record, datefmt=None):
380 Return the creation time of the specified LogRecord as formatted text.
382 This method should be called from format() by a formatter which
383 wants to make use of a formatted time. This method can be overridden
384 in formatters to provide for any specific requirement, but the
385 basic behaviour is as follows: if datefmt (a string) is specified,
386 it is used with time.strftime() to format the creation time of the
387 record. Otherwise, the ISO8601 format is used. The resulting
388 string is returned. This function uses a user-configurable function
389 to convert the creation time to a tuple. By default, time.localtime()
390 is used; to change this for a particular formatter instance, set the
391 'converter' attribute to a function with the same signature as
392 time.localtime() or time.gmtime(). To change it for all formatters,
393 for example if you want all logging times to be shown in GMT,
394 set the 'converter' attribute in the Formatter class.
396 ct = self.converter(record.created)
397 if datefmt:
398 s = time.strftime(datefmt, ct)
399 else:
400 t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
401 s = "%s,%03d" % (t, record.msecs)
402 return s
404 def formatException(self, ei):
406 Format and return the specified exception information as a string.
408 This default implementation just uses
409 traceback.print_exception()
411 sio = cStringIO.StringIO()
412 traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
413 s = sio.getvalue()
414 sio.close()
415 if s[-1:] == "\n":
416 s = s[:-1]
417 return s
419 def format(self, record):
421 Format the specified record as text.
423 The record's attribute dictionary is used as the operand to a
424 string formatting operation which yields the returned string.
425 Before formatting the dictionary, a couple of preparatory steps
426 are carried out. The message attribute of the record is computed
427 using LogRecord.getMessage(). If the formatting string contains
428 "%(asctime)", formatTime() is called to format the event time.
429 If there is exception information, it is formatted using
430 formatException() and appended to the message.
432 record.message = record.getMessage()
433 if string.find(self._fmt,"%(asctime)") >= 0:
434 record.asctime = self.formatTime(record, self.datefmt)
435 s = self._fmt % record.__dict__
436 if record.exc_info:
437 # Cache the traceback text to avoid converting it multiple times
438 # (it's constant anyway)
439 if not record.exc_text:
440 record.exc_text = self.formatException(record.exc_info)
441 if record.exc_text:
442 if s[-1:] != "\n":
443 s = s + "\n"
444 s = s + record.exc_text
445 return s
448 # The default formatter to use when no other is specified
450 _defaultFormatter = Formatter()
452 class BufferingFormatter:
454 A formatter suitable for formatting a number of records.
456 def __init__(self, linefmt=None):
458 Optionally specify a formatter which will be used to format each
459 individual record.
461 if linefmt:
462 self.linefmt = linefmt
463 else:
464 self.linefmt = _defaultFormatter
466 def formatHeader(self, records):
468 Return the header string for the specified records.
470 return ""
472 def formatFooter(self, records):
474 Return the footer string for the specified records.
476 return ""
478 def format(self, records):
480 Format the specified records and return the result as a string.
482 rv = ""
483 if len(records) > 0:
484 rv = rv + self.formatHeader(records)
485 for record in records:
486 rv = rv + self.linefmt.format(record)
487 rv = rv + self.formatFooter(records)
488 return rv
490 #---------------------------------------------------------------------------
491 # Filter classes and functions
492 #---------------------------------------------------------------------------
494 class Filter:
496 Filter instances are used to perform arbitrary filtering of LogRecords.
498 Loggers and Handlers can optionally use Filter instances to filter
499 records as desired. The base filter class only allows events which are
500 below a certain point in the logger hierarchy. For example, a filter
501 initialized with "A.B" will allow events logged by loggers "A.B",
502 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
503 initialized with the empty string, all events are passed.
505 def __init__(self, name=''):
507 Initialize a filter.
509 Initialize with the name of the logger which, together with its
510 children, will have its events allowed through the filter. If no
511 name is specified, allow every event.
513 self.name = name
514 self.nlen = len(name)
516 def filter(self, record):
518 Determine if the specified record is to be logged.
520 Is the specified record to be logged? Returns 0 for no, nonzero for
521 yes. If deemed appropriate, the record may be modified in-place.
523 if self.nlen == 0:
524 return 1
525 elif self.name == record.name:
526 return 1
527 elif string.find(record.name, self.name, 0, self.nlen) != 0:
528 return 0
529 return (record.name[self.nlen] == ".")
531 class Filterer:
533 A base class for loggers and handlers which allows them to share
534 common code.
536 def __init__(self):
538 Initialize the list of filters to be an empty list.
540 self.filters = []
542 def addFilter(self, filter):
544 Add the specified filter to this handler.
546 if not (filter in self.filters):
547 self.filters.append(filter)
549 def removeFilter(self, filter):
551 Remove the specified filter from this handler.
553 if filter in self.filters:
554 self.filters.remove(filter)
556 def filter(self, record):
558 Determine if a record is loggable by consulting all the filters.
560 The default is to allow the record to be logged; any filter can veto
561 this and the record is then dropped. Returns a zero value if a record
562 is to be dropped, else non-zero.
564 rv = 1
565 for f in self.filters:
566 if not f.filter(record):
567 rv = 0
568 break
569 return rv
571 #---------------------------------------------------------------------------
572 # Handler classes and functions
573 #---------------------------------------------------------------------------
575 _handlers = {} #repository of handlers (for flushing when shutdown called)
576 _handlerList = [] # added to allow handlers to be removed in reverse of order initialized
578 class Handler(Filterer):
580 Handler instances dispatch logging events to specific destinations.
582 The base handler class. Acts as a placeholder which defines the Handler
583 interface. Handlers can optionally use Formatter instances to format
584 records as desired. By default, no formatter is specified; in this case,
585 the 'raw' message as determined by record.message is logged.
587 def __init__(self, level=NOTSET):
589 Initializes the instance - basically setting the formatter to None
590 and the filter list to empty.
592 Filterer.__init__(self)
593 self.level = level
594 self.formatter = None
595 #get the module data lock, as we're updating a shared structure.
596 _acquireLock()
597 try: #unlikely to raise an exception, but you never know...
598 _handlers[self] = 1
599 _handlerList.insert(0, self)
600 finally:
601 _releaseLock()
602 self.createLock()
604 def createLock(self):
606 Acquire a thread lock for serializing access to the underlying I/O.
608 if thread:
609 self.lock = threading.RLock()
610 else:
611 self.lock = None
613 def acquire(self):
615 Acquire the I/O thread lock.
617 if self.lock:
618 self.lock.acquire()
620 def release(self):
622 Release the I/O thread lock.
624 if self.lock:
625 self.lock.release()
627 def setLevel(self, level):
629 Set the logging level of this handler.
631 self.level = level
633 def format(self, record):
635 Format the specified record.
637 If a formatter is set, use it. Otherwise, use the default formatter
638 for the module.
640 if self.formatter:
641 fmt = self.formatter
642 else:
643 fmt = _defaultFormatter
644 return fmt.format(record)
646 def emit(self, record):
648 Do whatever it takes to actually log the specified logging record.
650 This version is intended to be implemented by subclasses and so
651 raises a NotImplementedError.
653 raise NotImplementedError, 'emit must be implemented '\
654 'by Handler subclasses'
656 def handle(self, record):
658 Conditionally emit the specified logging record.
660 Emission depends on filters which may have been added to the handler.
661 Wrap the actual emission of the record with acquisition/release of
662 the I/O thread lock. Returns whether the filter passed the record for
663 emission.
665 rv = self.filter(record)
666 if rv:
667 self.acquire()
668 try:
669 self.emit(record)
670 finally:
671 self.release()
672 return rv
674 def setFormatter(self, fmt):
676 Set the formatter for this handler.
678 self.formatter = fmt
680 def flush(self):
682 Ensure all logging output has been flushed.
684 This version does nothing and is intended to be implemented by
685 subclasses.
687 pass
689 def close(self):
691 Tidy up any resources used by the handler.
693 This version does removes the handler from an internal list
694 of handlers which is closed when shutdown() is called. Subclasses
695 should ensure that this gets called from overridden close()
696 methods.
698 #get the module data lock, as we're updating a shared structure.
699 _acquireLock()
700 try: #unlikely to raise an exception, but you never know...
701 del _handlers[self]
702 _handlerList.remove(self)
703 finally:
704 _releaseLock()
706 def handleError(self, record):
708 Handle errors which occur during an emit() call.
710 This method should be called from handlers when an exception is
711 encountered during an emit() call. If raiseExceptions is false,
712 exceptions get silently ignored. This is what is mostly wanted
713 for a logging system - most users will not care about errors in
714 the logging system, they are more interested in application errors.
715 You could, however, replace this with a custom handler if you wish.
716 The record which was being processed is passed in to this method.
718 if raiseExceptions:
719 ei = sys.exc_info()
720 traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
721 del ei
723 class StreamHandler(Handler):
725 A handler class which writes logging records, appropriately formatted,
726 to a stream. Note that this class does not close the stream, as
727 sys.stdout or sys.stderr may be used.
730 def __init__(self, strm=None):
732 Initialize the handler.
734 If strm is not specified, sys.stderr is used.
736 Handler.__init__(self)
737 if strm is None:
738 strm = sys.stderr
739 self.stream = strm
741 def flush(self):
743 Flushes the stream.
745 if self.stream and hasattr(self.stream, "flush"):
746 self.stream.flush()
748 def emit(self, record):
750 Emit a record.
752 If a formatter is specified, it is used to format the record.
753 The record is then written to the stream with a trailing newline. If
754 exception information is present, it is formatted using
755 traceback.print_exception and appended to the stream. If the stream
756 has an 'encoding' attribute, it is used to encode the message before
757 output to the stream.
759 try:
760 msg = self.format(record)
761 stream = self.stream
762 fs = "%s\n"
763 if not hasattr(types, "UnicodeType"): #if no unicode support...
764 stream.write(fs % msg)
765 else:
766 try:
767 if (isinstance(msg, unicode) or
768 getattr(stream, 'encoding', None) is None):
769 stream.write(fs % msg)
770 else:
771 stream.write(fs % msg.encode(stream.encoding))
772 except UnicodeError:
773 stream.write(fs % msg.encode("UTF-8"))
774 self.flush()
775 except (KeyboardInterrupt, SystemExit):
776 raise
777 except:
778 self.handleError(record)
780 class FileHandler(StreamHandler):
782 A handler class which writes formatted logging records to disk files.
784 def __init__(self, filename, mode='a', encoding=None, delay=0):
786 Open the specified file and use it as the stream for logging.
788 #keep the absolute path, otherwise derived classes which use this
789 #may come a cropper when the current directory changes
790 if codecs is None:
791 encoding = None
792 self.baseFilename = os.path.abspath(filename)
793 self.mode = mode
794 self.encoding = encoding
795 if delay:
796 #We don't open the stream, but we still need to call the
797 #Handler constructor to set level, formatter, lock etc.
798 Handler.__init__(self)
799 self.stream = None
800 else:
801 StreamHandler.__init__(self, self._open())
803 def close(self):
805 Closes the stream.
807 if self.stream:
808 self.flush()
809 if hasattr(self.stream, "close"):
810 self.stream.close()
811 StreamHandler.close(self)
812 self.stream = None
814 def _open(self):
816 Open the current base file with the (original) mode and encoding.
817 Return the resulting stream.
819 if self.encoding is None:
820 stream = open(self.baseFilename, self.mode)
821 else:
822 stream = codecs.open(self.baseFilename, self.mode, self.encoding)
823 return stream
825 def emit(self, record):
827 Emit a record.
829 If the stream was not opened because 'delay' was specified in the
830 constructor, open it before calling the superclass's emit.
832 if self.stream is None:
833 self.stream = self._open()
834 StreamHandler.emit(self, record)
836 #---------------------------------------------------------------------------
837 # Manager classes and functions
838 #---------------------------------------------------------------------------
840 class PlaceHolder:
842 PlaceHolder instances are used in the Manager logger hierarchy to take
843 the place of nodes for which no loggers have been defined. This class is
844 intended for internal use only and not as part of the public API.
846 def __init__(self, alogger):
848 Initialize with the specified logger being a child of this placeholder.
850 #self.loggers = [alogger]
851 self.loggerMap = { alogger : None }
853 def append(self, alogger):
855 Add the specified logger as a child of this placeholder.
857 #if alogger not in self.loggers:
858 if alogger not in self.loggerMap:
859 #self.loggers.append(alogger)
860 self.loggerMap[alogger] = None
863 # Determine which class to use when instantiating loggers.
865 _loggerClass = None
867 def setLoggerClass(klass):
869 Set the class to be used when instantiating a logger. The class should
870 define __init__() such that only a name argument is required, and the
871 __init__() should call Logger.__init__()
873 if klass != Logger:
874 if not issubclass(klass, Logger):
875 raise TypeError, "logger not derived from logging.Logger: " + \
876 klass.__name__
877 global _loggerClass
878 _loggerClass = klass
880 def getLoggerClass():
882 Return the class to be used when instantiating a logger.
885 return _loggerClass
887 class Manager:
889 There is [under normal circumstances] just one Manager instance, which
890 holds the hierarchy of loggers.
892 def __init__(self, rootnode):
894 Initialize the manager with the root node of the logger hierarchy.
896 self.root = rootnode
897 self.disable = 0
898 self.emittedNoHandlerWarning = 0
899 self.loggerDict = {}
901 def getLogger(self, name):
903 Get a logger with the specified name (channel name), creating it
904 if it doesn't yet exist. This name is a dot-separated hierarchical
905 name, such as "a", "a.b", "a.b.c" or similar.
907 If a PlaceHolder existed for the specified name [i.e. the logger
908 didn't exist but a child of it did], replace it with the created
909 logger and fix up the parent/child references which pointed to the
910 placeholder to now point to the logger.
912 rv = None
913 _acquireLock()
914 try:
915 if name in self.loggerDict:
916 rv = self.loggerDict[name]
917 if isinstance(rv, PlaceHolder):
918 ph = rv
919 rv = _loggerClass(name)
920 rv.manager = self
921 self.loggerDict[name] = rv
922 self._fixupChildren(ph, rv)
923 self._fixupParents(rv)
924 else:
925 rv = _loggerClass(name)
926 rv.manager = self
927 self.loggerDict[name] = rv
928 self._fixupParents(rv)
929 finally:
930 _releaseLock()
931 return rv
933 def _fixupParents(self, alogger):
935 Ensure that there are either loggers or placeholders all the way
936 from the specified logger to the root of the logger hierarchy.
938 name = alogger.name
939 i = string.rfind(name, ".")
940 rv = None
941 while (i > 0) and not rv:
942 substr = name[:i]
943 if substr not in self.loggerDict:
944 self.loggerDict[substr] = PlaceHolder(alogger)
945 else:
946 obj = self.loggerDict[substr]
947 if isinstance(obj, Logger):
948 rv = obj
949 else:
950 assert isinstance(obj, PlaceHolder)
951 obj.append(alogger)
952 i = string.rfind(name, ".", 0, i - 1)
953 if not rv:
954 rv = self.root
955 alogger.parent = rv
957 def _fixupChildren(self, ph, alogger):
959 Ensure that children of the placeholder ph are connected to the
960 specified logger.
962 name = alogger.name
963 namelen = len(name)
964 for c in ph.loggerMap.keys():
965 #The if means ... if not c.parent.name.startswith(nm)
966 #if string.find(c.parent.name, nm) <> 0:
967 if c.parent.name[:namelen] != name:
968 alogger.parent = c.parent
969 c.parent = alogger
971 #---------------------------------------------------------------------------
972 # Logger classes and functions
973 #---------------------------------------------------------------------------
975 class Logger(Filterer):
977 Instances of the Logger class represent a single logging channel. A
978 "logging channel" indicates an area of an application. Exactly how an
979 "area" is defined is up to the application developer. Since an
980 application can have any number of areas, logging channels are identified
981 by a unique string. Application areas can be nested (e.g. an area
982 of "input processing" might include sub-areas "read CSV files", "read
983 XLS files" and "read Gnumeric files"). To cater for this natural nesting,
984 channel names are organized into a namespace hierarchy where levels are
985 separated by periods, much like the Java or Python package namespace. So
986 in the instance given above, channel names might be "input" for the upper
987 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
988 There is no arbitrary limit to the depth of nesting.
990 def __init__(self, name, level=NOTSET):
992 Initialize the logger with a name and an optional level.
994 Filterer.__init__(self)
995 self.name = name
996 self.level = level
997 self.parent = None
998 self.propagate = 1
999 self.handlers = []
1000 self.disabled = 0
1002 def setLevel(self, level):
1004 Set the logging level of this logger.
1006 self.level = level
1008 def debug(self, msg, *args, **kwargs):
1010 Log 'msg % args' with severity 'DEBUG'.
1012 To pass exception information, use the keyword argument exc_info with
1013 a true value, e.g.
1015 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
1017 if self.isEnabledFor(DEBUG):
1018 self._log(DEBUG, msg, args, **kwargs)
1020 def info(self, msg, *args, **kwargs):
1022 Log 'msg % args' with severity 'INFO'.
1024 To pass exception information, use the keyword argument exc_info with
1025 a true value, e.g.
1027 logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
1029 if self.isEnabledFor(INFO):
1030 self._log(INFO, msg, args, **kwargs)
1032 def warning(self, msg, *args, **kwargs):
1034 Log 'msg % args' with severity 'WARNING'.
1036 To pass exception information, use the keyword argument exc_info with
1037 a true value, e.g.
1039 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
1041 if self.isEnabledFor(WARNING):
1042 self._log(WARNING, msg, args, **kwargs)
1044 warn = warning
1046 def error(self, msg, *args, **kwargs):
1048 Log 'msg % args' with severity 'ERROR'.
1050 To pass exception information, use the keyword argument exc_info with
1051 a true value, e.g.
1053 logger.error("Houston, we have a %s", "major problem", exc_info=1)
1055 if self.isEnabledFor(ERROR):
1056 self._log(ERROR, msg, args, **kwargs)
1058 def exception(self, msg, *args):
1060 Convenience method for logging an ERROR with exception information.
1062 self.error(*((msg,) + args), **{'exc_info': 1})
1064 def critical(self, msg, *args, **kwargs):
1066 Log 'msg % args' with severity 'CRITICAL'.
1068 To pass exception information, use the keyword argument exc_info with
1069 a true value, e.g.
1071 logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
1073 if self.isEnabledFor(CRITICAL):
1074 self._log(CRITICAL, msg, args, **kwargs)
1076 fatal = critical
1078 def log(self, level, msg, *args, **kwargs):
1080 Log 'msg % args' with the integer severity 'level'.
1082 To pass exception information, use the keyword argument exc_info with
1083 a true value, e.g.
1085 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1087 if type(level) != types.IntType:
1088 if raiseExceptions:
1089 raise TypeError, "level must be an integer"
1090 else:
1091 return
1092 if self.isEnabledFor(level):
1093 self._log(level, msg, args, **kwargs)
1095 def findCaller(self):
1097 Find the stack frame of the caller so that we can note the source
1098 file name, line number and function name.
1100 f = currentframe().f_back
1101 rv = "(unknown file)", 0, "(unknown function)"
1102 while hasattr(f, "f_code"):
1103 co = f.f_code
1104 filename = os.path.normcase(co.co_filename)
1105 if filename == _srcfile:
1106 f = f.f_back
1107 continue
1108 rv = (filename, f.f_lineno, co.co_name)
1109 break
1110 return rv
1112 def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None):
1114 A factory method which can be overridden in subclasses to create
1115 specialized LogRecords.
1117 rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func)
1118 if extra is not None:
1119 for key in extra:
1120 if (key in ["message", "asctime"]) or (key in rv.__dict__):
1121 raise KeyError("Attempt to overwrite %r in LogRecord" % key)
1122 rv.__dict__[key] = extra[key]
1123 return rv
1125 def _log(self, level, msg, args, exc_info=None, extra=None):
1127 Low-level logging routine which creates a LogRecord and then calls
1128 all the handlers of this logger to handle the record.
1130 if _srcfile:
1131 #IronPython doesn't track Python frames, so findCaller throws an
1132 #exception. We trap it here so that IronPython can use logging.
1133 try:
1134 fn, lno, func = self.findCaller()
1135 except ValueError:
1136 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1137 else:
1138 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1139 if exc_info:
1140 if type(exc_info) != types.TupleType:
1141 exc_info = sys.exc_info()
1142 record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra)
1143 self.handle(record)
1145 def handle(self, record):
1147 Call the handlers for the specified record.
1149 This method is used for unpickled records received from a socket, as
1150 well as those created locally. Logger-level filtering is applied.
1152 if (not self.disabled) and self.filter(record):
1153 self.callHandlers(record)
1155 def addHandler(self, hdlr):
1157 Add the specified handler to this logger.
1159 if not (hdlr in self.handlers):
1160 self.handlers.append(hdlr)
1162 def removeHandler(self, hdlr):
1164 Remove the specified handler from this logger.
1166 if hdlr in self.handlers:
1167 #hdlr.close()
1168 hdlr.acquire()
1169 try:
1170 self.handlers.remove(hdlr)
1171 finally:
1172 hdlr.release()
1174 def callHandlers(self, record):
1176 Pass a record to all relevant handlers.
1178 Loop through all handlers for this logger and its parents in the
1179 logger hierarchy. If no handler was found, output a one-off error
1180 message to sys.stderr. Stop searching up the hierarchy whenever a
1181 logger with the "propagate" attribute set to zero is found - that
1182 will be the last logger whose handlers are called.
1184 c = self
1185 found = 0
1186 while c:
1187 for hdlr in c.handlers:
1188 found = found + 1
1189 if record.levelno >= hdlr.level:
1190 hdlr.handle(record)
1191 if not c.propagate:
1192 c = None #break out
1193 else:
1194 c = c.parent
1195 if (found == 0) and raiseExceptions and not self.manager.emittedNoHandlerWarning:
1196 sys.stderr.write("No handlers could be found for logger"
1197 " \"%s\"\n" % self.name)
1198 self.manager.emittedNoHandlerWarning = 1
1200 def getEffectiveLevel(self):
1202 Get the effective level for this logger.
1204 Loop through this logger and its parents in the logger hierarchy,
1205 looking for a non-zero logging level. Return the first one found.
1207 logger = self
1208 while logger:
1209 if logger.level:
1210 return logger.level
1211 logger = logger.parent
1212 return NOTSET
1214 def isEnabledFor(self, level):
1216 Is this logger enabled for level 'level'?
1218 if self.manager.disable >= level:
1219 return 0
1220 return level >= self.getEffectiveLevel()
1222 class RootLogger(Logger):
1224 A root logger is not that different to any other logger, except that
1225 it must have a logging level and there is only one instance of it in
1226 the hierarchy.
1228 def __init__(self, level):
1230 Initialize the logger with the name "root".
1232 Logger.__init__(self, "root", level)
1234 _loggerClass = Logger
1236 class LoggerAdapter:
1238 An adapter for loggers which makes it easier to specify contextual
1239 information in logging output.
1242 def __init__(self, logger, extra):
1244 Initialize the adapter with a logger and a dict-like object which
1245 provides contextual information. This constructor signature allows
1246 easy stacking of LoggerAdapters, if so desired.
1248 You can effectively pass keyword arguments as shown in the
1249 following example:
1251 adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
1253 self.logger = logger
1254 self.extra = extra
1256 def process(self, msg, kwargs):
1258 Process the logging message and keyword arguments passed in to
1259 a logging call to insert contextual information. You can either
1260 manipulate the message itself, the keyword args or both. Return
1261 the message and kwargs modified (or not) to suit your needs.
1263 Normally, you'll only need to override this one method in a
1264 LoggerAdapter subclass for your specific needs.
1266 kwargs["extra"] = self.extra
1267 return msg, kwargs
1269 def debug(self, msg, *args, **kwargs):
1271 Delegate a debug call to the underlying logger, after adding
1272 contextual information from this adapter instance.
1274 msg, kwargs = self.process(msg, kwargs)
1275 self.logger.debug(msg, *args, **kwargs)
1277 def info(self, msg, *args, **kwargs):
1279 Delegate an info call to the underlying logger, after adding
1280 contextual information from this adapter instance.
1282 msg, kwargs = self.process(msg, kwargs)
1283 self.logger.info(msg, *args, **kwargs)
1285 def warning(self, msg, *args, **kwargs):
1287 Delegate a warning call to the underlying logger, after adding
1288 contextual information from this adapter instance.
1290 msg, kwargs = self.process(msg, kwargs)
1291 self.logger.warning(msg, *args, **kwargs)
1293 def error(self, msg, *args, **kwargs):
1295 Delegate an error call to the underlying logger, after adding
1296 contextual information from this adapter instance.
1298 msg, kwargs = self.process(msg, kwargs)
1299 self.logger.error(msg, *args, **kwargs)
1301 def exception(self, msg, *args, **kwargs):
1303 Delegate an exception call to the underlying logger, after adding
1304 contextual information from this adapter instance.
1306 msg, kwargs = self.process(msg, kwargs)
1307 kwargs["exc_info"] = 1
1308 self.logger.error(msg, *args, **kwargs)
1310 def critical(self, msg, *args, **kwargs):
1312 Delegate a critical call to the underlying logger, after adding
1313 contextual information from this adapter instance.
1315 msg, kwargs = self.process(msg, kwargs)
1316 self.logger.critical(msg, *args, **kwargs)
1318 def log(self, level, msg, *args, **kwargs):
1320 Delegate a log call to the underlying logger, after adding
1321 contextual information from this adapter instance.
1323 msg, kwargs = self.process(msg, kwargs)
1324 self.logger.log(level, msg, *args, **kwargs)
1326 root = RootLogger(WARNING)
1327 Logger.root = root
1328 Logger.manager = Manager(Logger.root)
1330 #---------------------------------------------------------------------------
1331 # Configuration classes and functions
1332 #---------------------------------------------------------------------------
1334 BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
1336 def basicConfig(**kwargs):
1338 Do basic configuration for the logging system.
1340 This function does nothing if the root logger already has handlers
1341 configured. It is a convenience method intended for use by simple scripts
1342 to do one-shot configuration of the logging package.
1344 The default behaviour is to create a StreamHandler which writes to
1345 sys.stderr, set a formatter using the BASIC_FORMAT format string, and
1346 add the handler to the root logger.
1348 A number of optional keyword arguments may be specified, which can alter
1349 the default behaviour.
1351 filename Specifies that a FileHandler be created, using the specified
1352 filename, rather than a StreamHandler.
1353 filemode Specifies the mode to open the file, if filename is specified
1354 (if filemode is unspecified, it defaults to 'a').
1355 format Use the specified format string for the handler.
1356 datefmt Use the specified date/time format.
1357 level Set the root logger level to the specified level.
1358 stream Use the specified stream to initialize the StreamHandler. Note
1359 that this argument is incompatible with 'filename' - if both
1360 are present, 'stream' is ignored.
1362 Note that you could specify a stream created using open(filename, mode)
1363 rather than passing the filename and mode in. However, it should be
1364 remembered that StreamHandler does not close its stream (since it may be
1365 using sys.stdout or sys.stderr), whereas FileHandler closes its stream
1366 when the handler is closed.
1368 if len(root.handlers) == 0:
1369 filename = kwargs.get("filename")
1370 if filename:
1371 mode = kwargs.get("filemode", 'a')
1372 hdlr = FileHandler(filename, mode)
1373 else:
1374 stream = kwargs.get("stream")
1375 hdlr = StreamHandler(stream)
1376 fs = kwargs.get("format", BASIC_FORMAT)
1377 dfs = kwargs.get("datefmt", None)
1378 fmt = Formatter(fs, dfs)
1379 hdlr.setFormatter(fmt)
1380 root.addHandler(hdlr)
1381 level = kwargs.get("level")
1382 if level is not None:
1383 root.setLevel(level)
1385 #---------------------------------------------------------------------------
1386 # Utility functions at module level.
1387 # Basically delegate everything to the root logger.
1388 #---------------------------------------------------------------------------
1390 def getLogger(name=None):
1392 Return a logger with the specified name, creating it if necessary.
1394 If no name is specified, return the root logger.
1396 if name:
1397 return Logger.manager.getLogger(name)
1398 else:
1399 return root
1401 #def getRootLogger():
1402 # """
1403 # Return the root logger.
1405 # Note that getLogger('') now does the same thing, so this function is
1406 # deprecated and may disappear in the future.
1407 # """
1408 # return root
1410 def critical(msg, *args, **kwargs):
1412 Log a message with severity 'CRITICAL' on the root logger.
1414 if len(root.handlers) == 0:
1415 basicConfig()
1416 root.critical(*((msg,)+args), **kwargs)
1418 fatal = critical
1420 def error(msg, *args, **kwargs):
1422 Log a message with severity 'ERROR' on the root logger.
1424 if len(root.handlers) == 0:
1425 basicConfig()
1426 root.error(*((msg,)+args), **kwargs)
1428 def exception(msg, *args):
1430 Log a message with severity 'ERROR' on the root logger,
1431 with exception information.
1433 error(*((msg,)+args), **{'exc_info': 1})
1435 def warning(msg, *args, **kwargs):
1437 Log a message with severity 'WARNING' on the root logger.
1439 if len(root.handlers) == 0:
1440 basicConfig()
1441 root.warning(*((msg,)+args), **kwargs)
1443 warn = warning
1445 def info(msg, *args, **kwargs):
1447 Log a message with severity 'INFO' on the root logger.
1449 if len(root.handlers) == 0:
1450 basicConfig()
1451 root.info(*((msg,)+args), **kwargs)
1453 def debug(msg, *args, **kwargs):
1455 Log a message with severity 'DEBUG' on the root logger.
1457 if len(root.handlers) == 0:
1458 basicConfig()
1459 root.debug(*((msg,)+args), **kwargs)
1461 def log(level, msg, *args, **kwargs):
1463 Log 'msg % args' with the integer severity 'level' on the root logger.
1465 if len(root.handlers) == 0:
1466 basicConfig()
1467 root.log(*((level, msg)+args), **kwargs)
1469 def disable(level):
1471 Disable all logging calls less severe than 'level'.
1473 root.manager.disable = level
1475 def shutdown(handlerList=_handlerList):
1477 Perform any cleanup actions in the logging system (e.g. flushing
1478 buffers).
1480 Should be called at application exit.
1482 for h in handlerList[:]:
1483 #errors might occur, for example, if files are locked
1484 #we just ignore them if raiseExceptions is not set
1485 try:
1486 h.flush()
1487 h.close()
1488 except:
1489 if raiseExceptions:
1490 raise
1491 #else, swallow
1493 #Let's try and shutdown automatically on application exit...
1494 try:
1495 import atexit
1496 atexit.register(shutdown)
1497 except ImportError: # for Python versions < 2.0
1498 def exithook(status, old_exit=sys.exit):
1499 try:
1500 shutdown()
1501 finally:
1502 old_exit(status)
1504 sys.exit = exithook
1506 # Null handler
1508 class NullHandler(Handler):
1510 This handler does nothing. It's intended to be used to avoid the
1511 "No handlers could be found for logger XXX" one-off warning. This is
1512 important for library code, which may contain code to log events. If a user
1513 of the library does not configure logging, the one-off warning might be
1514 produced; to avoid this, the library developer simply needs to instantiate
1515 a NullHandler and add it to the top-level logger of the library module or
1516 package.
1518 def emit(self, record):
1519 pass
1521 # Warnings integration
1523 _warnings_showwarning = None
1525 def _showwarning(message, category, filename, lineno, file=None, line=None):
1527 Implementation of showwarnings which redirects to logging, which will first
1528 check to see if the file parameter is None. If a file is specified, it will
1529 delegate to the original warnings implementation of showwarning. Otherwise,
1530 it will call warnings.formatwarning and will log the resulting string to a
1531 warnings logger named "py.warnings" with level logging.WARNING.
1533 if file is not None:
1534 if _warnings_showwarning is not None:
1535 _warnings_showwarning(message, category, filename, lineno, file, line)
1536 else:
1537 s = warnings.formatwarning(message, category, filename, lineno, line)
1538 logger = getLogger("py.warnings")
1539 if not logger.handlers:
1540 logger.addHandler(NullHandler())
1541 logger.warning("%s", s)
1543 def captureWarnings(capture):
1545 If capture is true, redirect all warnings to the logging package.
1546 If capture is False, ensure that warnings are not redirected to logging
1547 but to their original destinations.
1549 global _warnings_showwarning
1550 if capture:
1551 if _warnings_showwarning is None:
1552 _warnings_showwarning = warnings.showwarning
1553 warnings.showwarning = _showwarning
1554 else:
1555 if _warnings_showwarning is not None:
1556 warnings.showwarning = _warnings_showwarning
1557 _warnings_showwarning = None