1 # Copyright 2001-2008 by Vinay Sajip. All Rights Reserved.
3 # Permission to use, copy, modify, and distribute this software and its
4 # documentation for any purpose and without fee is hereby granted,
5 # provided that the above copyright notice appear in all copies and that
6 # both that copyright notice and this permission notice appear in
7 # supporting documentation, and that the name of Vinay Sajip
8 # not be used in advertising or publicity pertaining to distribution
9 # of the software without specific, written prior permission.
10 # VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
11 # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
12 # VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
13 # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
14 # IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 Logging package for Python. Based on PEP 282 and comments thereto in
19 comp.lang.python, and influenced by Apache's log4j system.
21 Should work under Python versions >= 1.5.2, except that source line
22 information is not available unless 'sys._getframe()' is.
24 Copyright (C) 2001-2008 Vinay Sajip. All Rights Reserved.
26 To use, simply 'import logging' and log away!
29 import sys
, os
, types
, time
, string
, cStringIO
, traceback
42 __author__
= "Vinay Sajip <vinay_sajip@red-dove.com>"
43 __status__
= "production"
44 __version__
= "0.5.0.4"
45 __date__
= "18 January 2008"
47 #---------------------------------------------------------------------------
48 # Miscellaneous module data
49 #---------------------------------------------------------------------------
52 # _srcfile is used when walking the stack to check when we've got the first
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'
61 _srcfile
= os
.path
.normcase(_srcfile
)
63 # next bit filched from 1.5.2's inspect.py
65 """Return the frame object for the caller's stack frame."""
69 return sys
.exc_traceback
.tb_frame
.f_back
71 if hasattr(sys
, '_getframe'): currentframe
= lambda: sys
._getframe
(3)
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"):
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
93 # If you don't want threading information in the log, set this to zero
98 # If you don't want process information in the log, set this to zero
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.
123 CRITICAL
: 'CRITICAL',
129 'CRITICAL' : CRITICAL
,
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.
161 try: #unlikely to cause an exception, but you never know...
162 _levelNames
[level
] = levelName
163 _levelNames
[levelName
] = level
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.
183 Acquire the module-level lock for serializing access to shared data.
185 This should be released with _releaseLock().
188 if (not _lock
) and thread
:
189 _lock
= threading
.RLock()
195 Release the module-level lock acquired by calling _acquireLock().
200 #---------------------------------------------------------------------------
202 #---------------------------------------------------------------------------
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.
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
237 if args
and len(args
) == 1 and (
238 type(args
[0]) == types
.DictType
242 self
.levelname
= getLevelName(level
)
244 self
.pathname
= pathname
246 self
.filename
= os
.path
.basename(pathname
)
247 self
.module
= os
.path
.splitext(self
.filename
)[0]
248 except (TypeError, ValueError, AttributeError):
249 self
.filename
= pathname
250 self
.module
= "Unknown module"
251 self
.exc_info
= exc_info
252 self
.exc_text
= None # used to cache the traceback text
256 self
.msecs
= (ct
- long(ct
)) * 1000
257 self
.relativeCreated
= (self
.created
- _startTime
) * 1000
258 if logThreads
and thread
:
259 self
.thread
= thread
.get_ident()
260 self
.threadName
= threading
.currentThread().getName()
263 self
.threadName
= None
264 if logProcesses
and hasattr(os
, 'getpid'):
265 self
.process
= os
.getpid()
270 return '<LogRecord: %s, %s, %s, %s, "%s">'%(self
.name
, self
.levelno
,
271 self
.pathname
, self
.lineno
, self
.msg
)
273 def getMessage(self
):
275 Return the message for this LogRecord.
277 Return the message for this LogRecord after merging any user-supplied
278 arguments with the message.
280 if not hasattr(types
, "UnicodeType"): #if no unicode support...
284 if type(msg
) not in (types
.UnicodeType
, types
.StringType
):
288 msg
= self
.msg
#Defer encoding till later
290 msg
= msg
% self
.args
293 def makeLogRecord(dict):
295 Make a LogRecord whose attributes are defined by the specified dictionary,
296 This function is useful for converting a logging event received over
297 a socket connection (which is sent as a dictionary) into a LogRecord
300 rv
= LogRecord(None, None, "", 0, "", (), None, None)
301 rv
.__dict
__.update(dict)
304 #---------------------------------------------------------------------------
305 # Formatter classes and functions
306 #---------------------------------------------------------------------------
310 Formatter instances are used to convert a LogRecord to text.
312 Formatters need to know how a LogRecord is constructed. They are
313 responsible for converting a LogRecord to (usually) a string which can
314 be interpreted by either a human or an external system. The base Formatter
315 allows a formatting string to be specified. If none is supplied, the
316 default value of "%s(message)\\n" is used.
318 The Formatter can be initialized with a format string which makes use of
319 knowledge of the LogRecord attributes - e.g. the default value mentioned
320 above makes use of the fact that the user's message and arguments are pre-
321 formatted into a LogRecord's message attribute. Currently, the useful
322 attributes in a LogRecord are described by:
324 %(name)s Name of the logger (logging channel)
325 %(levelno)s Numeric logging level for the message (DEBUG, INFO,
326 WARNING, ERROR, CRITICAL)
327 %(levelname)s Text logging level for the message ("DEBUG", "INFO",
328 "WARNING", "ERROR", "CRITICAL")
329 %(pathname)s Full pathname of the source file where the logging
330 call was issued (if available)
331 %(filename)s Filename portion of pathname
332 %(module)s Module (name portion of filename)
333 %(lineno)d Source line number where the logging call was issued
335 %(funcName)s Function name
336 %(created)f Time when the LogRecord was created (time.time()
338 %(asctime)s Textual time when the LogRecord was created
339 %(msecs)d Millisecond portion of the creation time
340 %(relativeCreated)d Time in milliseconds when the LogRecord was created,
341 relative to the time the logging module was loaded
342 (typically at application startup time)
343 %(thread)d Thread ID (if available)
344 %(threadName)s Thread name (if available)
345 %(process)d Process ID (if available)
346 %(message)s The result of record.getMessage(), computed just as
347 the record is emitted
350 converter
= time
.localtime
352 def __init__(self
, fmt
=None, datefmt
=None):
354 Initialize the formatter with specified format strings.
356 Initialize the formatter either with the specified format string, or a
357 default as described above. Allow for specialized date formatting with
358 the optional datefmt argument (if omitted, you get the ISO8601 format).
363 self
._fmt
= "%(message)s"
364 self
.datefmt
= datefmt
366 def formatTime(self
, record
, datefmt
=None):
368 Return the creation time of the specified LogRecord as formatted text.
370 This method should be called from format() by a formatter which
371 wants to make use of a formatted time. This method can be overridden
372 in formatters to provide for any specific requirement, but the
373 basic behaviour is as follows: if datefmt (a string) is specified,
374 it is used with time.strftime() to format the creation time of the
375 record. Otherwise, the ISO8601 format is used. The resulting
376 string is returned. This function uses a user-configurable function
377 to convert the creation time to a tuple. By default, time.localtime()
378 is used; to change this for a particular formatter instance, set the
379 'converter' attribute to a function with the same signature as
380 time.localtime() or time.gmtime(). To change it for all formatters,
381 for example if you want all logging times to be shown in GMT,
382 set the 'converter' attribute in the Formatter class.
384 ct
= self
.converter(record
.created
)
386 s
= time
.strftime(datefmt
, ct
)
388 t
= time
.strftime("%Y-%m-%d %H:%M:%S", ct
)
389 s
= "%s,%03d" % (t
, record
.msecs
)
392 def formatException(self
, ei
):
394 Format and return the specified exception information as a string.
396 This default implementation just uses
397 traceback.print_exception()
399 sio
= cStringIO
.StringIO()
400 traceback
.print_exception(ei
[0], ei
[1], ei
[2], None, sio
)
407 def format(self
, record
):
409 Format the specified record as text.
411 The record's attribute dictionary is used as the operand to a
412 string formatting operation which yields the returned string.
413 Before formatting the dictionary, a couple of preparatory steps
414 are carried out. The message attribute of the record is computed
415 using LogRecord.getMessage(). If the formatting string contains
416 "%(asctime)", formatTime() is called to format the event time.
417 If there is exception information, it is formatted using
418 formatException() and appended to the message.
420 record
.message
= record
.getMessage()
421 if string
.find(self
._fmt
,"%(asctime)") >= 0:
422 record
.asctime
= self
.formatTime(record
, self
.datefmt
)
423 s
= self
._fmt
% record
.__dict
__
425 # Cache the traceback text to avoid converting it multiple times
426 # (it's constant anyway)
427 if not record
.exc_text
:
428 record
.exc_text
= self
.formatException(record
.exc_info
)
432 s
= s
+ record
.exc_text
436 # The default formatter to use when no other is specified
438 _defaultFormatter
= Formatter()
440 class BufferingFormatter
:
442 A formatter suitable for formatting a number of records.
444 def __init__(self
, linefmt
=None):
446 Optionally specify a formatter which will be used to format each
450 self
.linefmt
= linefmt
452 self
.linefmt
= _defaultFormatter
454 def formatHeader(self
, records
):
456 Return the header string for the specified records.
460 def formatFooter(self
, records
):
462 Return the footer string for the specified records.
466 def format(self
, records
):
468 Format the specified records and return the result as a string.
472 rv
= rv
+ self
.formatHeader(records
)
473 for record
in records
:
474 rv
= rv
+ self
.linefmt
.format(record
)
475 rv
= rv
+ self
.formatFooter(records
)
478 #---------------------------------------------------------------------------
479 # Filter classes and functions
480 #---------------------------------------------------------------------------
484 Filter instances are used to perform arbitrary filtering of LogRecords.
486 Loggers and Handlers can optionally use Filter instances to filter
487 records as desired. The base filter class only allows events which are
488 below a certain point in the logger hierarchy. For example, a filter
489 initialized with "A.B" will allow events logged by loggers "A.B",
490 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
491 initialized with the empty string, all events are passed.
493 def __init__(self
, name
=''):
497 Initialize with the name of the logger which, together with its
498 children, will have its events allowed through the filter. If no
499 name is specified, allow every event.
502 self
.nlen
= len(name
)
504 def filter(self
, record
):
506 Determine if the specified record is to be logged.
508 Is the specified record to be logged? Returns 0 for no, nonzero for
509 yes. If deemed appropriate, the record may be modified in-place.
513 elif self
.name
== record
.name
:
515 elif string
.find(record
.name
, self
.name
, 0, self
.nlen
) != 0:
517 return (record
.name
[self
.nlen
] == ".")
521 A base class for loggers and handlers which allows them to share
526 Initialize the list of filters to be an empty list.
530 def addFilter(self
, filter):
532 Add the specified filter to this handler.
534 if not (filter in self
.filters
):
535 self
.filters
.append(filter)
537 def removeFilter(self
, filter):
539 Remove the specified filter from this handler.
541 if filter in self
.filters
:
542 self
.filters
.remove(filter)
544 def filter(self
, record
):
546 Determine if a record is loggable by consulting all the filters.
548 The default is to allow the record to be logged; any filter can veto
549 this and the record is then dropped. Returns a zero value if a record
550 is to be dropped, else non-zero.
553 for f
in self
.filters
:
554 if not f
.filter(record
):
559 #---------------------------------------------------------------------------
560 # Handler classes and functions
561 #---------------------------------------------------------------------------
563 _handlers
= {} #repository of handlers (for flushing when shutdown called)
564 _handlerList
= [] # added to allow handlers to be removed in reverse of order initialized
566 class Handler(Filterer
):
568 Handler instances dispatch logging events to specific destinations.
570 The base handler class. Acts as a placeholder which defines the Handler
571 interface. Handlers can optionally use Formatter instances to format
572 records as desired. By default, no formatter is specified; in this case,
573 the 'raw' message as determined by record.message is logged.
575 def __init__(self
, level
=NOTSET
):
577 Initializes the instance - basically setting the formatter to None
578 and the filter list to empty.
580 Filterer
.__init
__(self
)
582 self
.formatter
= None
583 #get the module data lock, as we're updating a shared structure.
585 try: #unlikely to raise an exception, but you never know...
587 _handlerList
.insert(0, self
)
592 def createLock(self
):
594 Acquire a thread lock for serializing access to the underlying I/O.
597 self
.lock
= threading
.RLock()
603 Acquire the I/O thread lock.
610 Release the I/O thread lock.
615 def setLevel(self
, level
):
617 Set the logging level of this handler.
621 def format(self
, record
):
623 Format the specified record.
625 If a formatter is set, use it. Otherwise, use the default formatter
631 fmt
= _defaultFormatter
632 return fmt
.format(record
)
634 def emit(self
, record
):
636 Do whatever it takes to actually log the specified logging record.
638 This version is intended to be implemented by subclasses and so
639 raises a NotImplementedError.
641 raise NotImplementedError, 'emit must be implemented '\
642 'by Handler subclasses'
644 def handle(self
, record
):
646 Conditionally emit the specified logging record.
648 Emission depends on filters which may have been added to the handler.
649 Wrap the actual emission of the record with acquisition/release of
650 the I/O thread lock. Returns whether the filter passed the record for
653 rv
= self
.filter(record
)
662 def setFormatter(self
, fmt
):
664 Set the formatter for this handler.
670 Ensure all logging output has been flushed.
672 This version does nothing and is intended to be implemented by
679 Tidy up any resources used by the handler.
681 This version does removes the handler from an internal list
682 of handlers which is closed when shutdown() is called. Subclasses
683 should ensure that this gets called from overridden close()
686 #get the module data lock, as we're updating a shared structure.
688 try: #unlikely to raise an exception, but you never know...
690 _handlerList
.remove(self
)
694 def handleError(self
, record
):
696 Handle errors which occur during an emit() call.
698 This method should be called from handlers when an exception is
699 encountered during an emit() call. If raiseExceptions is false,
700 exceptions get silently ignored. This is what is mostly wanted
701 for a logging system - most users will not care about errors in
702 the logging system, they are more interested in application errors.
703 You could, however, replace this with a custom handler if you wish.
704 The record which was being processed is passed in to this method.
708 traceback
.print_exception(ei
[0], ei
[1], ei
[2], None, sys
.stderr
)
711 class StreamHandler(Handler
):
713 A handler class which writes logging records, appropriately formatted,
714 to a stream. Note that this class does not close the stream, as
715 sys.stdout or sys.stderr may be used.
717 def __init__(self
, strm
=None):
719 Initialize the handler.
721 If strm is not specified, sys.stderr is used.
723 Handler
.__init
__(self
)
727 self
.formatter
= None
736 def emit(self
, record
):
740 If a formatter is specified, it is used to format the record.
741 The record is then written to the stream with a trailing newline
742 [N.B. this may be removed depending on feedback]. If exception
743 information is present, it is formatted using
744 traceback.print_exception and appended to the stream.
747 msg
= self
.format(record
)
749 if not hasattr(types
, "UnicodeType"): #if no unicode support...
750 self
.stream
.write(fs
% msg
)
753 self
.stream
.write(fs
% msg
)
755 self
.stream
.write(fs
% msg
.encode("UTF-8"))
757 except (KeyboardInterrupt, SystemExit):
760 self
.handleError(record
)
762 class FileHandler(StreamHandler
):
764 A handler class which writes formatted logging records to disk files.
766 def __init__(self
, filename
, mode
='a', encoding
=None):
768 Open the specified file and use it as the stream for logging.
770 #keep the absolute path, otherwise derived classes which use this
771 #may come a cropper when the current directory changes
774 self
.baseFilename
= os
.path
.abspath(filename
)
776 self
.encoding
= encoding
777 stream
= self
._open
()
778 StreamHandler
.__init
__(self
, stream
)
787 StreamHandler
.close(self
)
792 Open the current base file with the (original) mode and encoding.
793 Return the resulting stream.
795 if self
.encoding
is None:
796 stream
= open(self
.baseFilename
, self
.mode
)
798 stream
= codecs
.open(self
.baseFilename
, self
.mode
, self
.encoding
)
801 #---------------------------------------------------------------------------
802 # Manager classes and functions
803 #---------------------------------------------------------------------------
807 PlaceHolder instances are used in the Manager logger hierarchy to take
808 the place of nodes for which no loggers have been defined. This class is
809 intended for internal use only and not as part of the public API.
811 def __init__(self
, alogger
):
813 Initialize with the specified logger being a child of this placeholder.
815 #self.loggers = [alogger]
816 self
.loggerMap
= { alogger
: None }
818 def append(self
, alogger
):
820 Add the specified logger as a child of this placeholder.
822 #if alogger not in self.loggers:
823 if not self
.loggerMap
.has_key(alogger
):
824 #self.loggers.append(alogger)
825 self
.loggerMap
[alogger
] = None
828 # Determine which class to use when instantiating loggers.
832 def setLoggerClass(klass
):
834 Set the class to be used when instantiating a logger. The class should
835 define __init__() such that only a name argument is required, and the
836 __init__() should call Logger.__init__()
839 if not issubclass(klass
, Logger
):
840 raise TypeError, "logger not derived from logging.Logger: " + \
845 def getLoggerClass():
847 Return the class to be used when instantiating a logger.
854 There is [under normal circumstances] just one Manager instance, which
855 holds the hierarchy of loggers.
857 def __init__(self
, rootnode
):
859 Initialize the manager with the root node of the logger hierarchy.
863 self
.emittedNoHandlerWarning
= 0
866 def getLogger(self
, name
):
868 Get a logger with the specified name (channel name), creating it
869 if it doesn't yet exist. This name is a dot-separated hierarchical
870 name, such as "a", "a.b", "a.b.c" or similar.
872 If a PlaceHolder existed for the specified name [i.e. the logger
873 didn't exist but a child of it did], replace it with the created
874 logger and fix up the parent/child references which pointed to the
875 placeholder to now point to the logger.
880 if self
.loggerDict
.has_key(name
):
881 rv
= self
.loggerDict
[name
]
882 if isinstance(rv
, PlaceHolder
):
884 rv
= _loggerClass(name
)
886 self
.loggerDict
[name
] = rv
887 self
._fixupChildren
(ph
, rv
)
888 self
._fixupParents
(rv
)
890 rv
= _loggerClass(name
)
892 self
.loggerDict
[name
] = rv
893 self
._fixupParents
(rv
)
898 def _fixupParents(self
, alogger
):
900 Ensure that there are either loggers or placeholders all the way
901 from the specified logger to the root of the logger hierarchy.
904 i
= string
.rfind(name
, ".")
906 while (i
> 0) and not rv
:
908 if not self
.loggerDict
.has_key(substr
):
909 self
.loggerDict
[substr
] = PlaceHolder(alogger
)
911 obj
= self
.loggerDict
[substr
]
912 if isinstance(obj
, Logger
):
915 assert isinstance(obj
, PlaceHolder
)
917 i
= string
.rfind(name
, ".", 0, i
- 1)
922 def _fixupChildren(self
, ph
, alogger
):
924 Ensure that children of the placeholder ph are connected to the
929 for c
in ph
.loggerMap
.keys():
930 #The if means ... if not c.parent.name.startswith(nm)
931 #if string.find(c.parent.name, nm) <> 0:
932 if c
.parent
.name
[:namelen
] != name
:
933 alogger
.parent
= c
.parent
936 #---------------------------------------------------------------------------
937 # Logger classes and functions
938 #---------------------------------------------------------------------------
940 class Logger(Filterer
):
942 Instances of the Logger class represent a single logging channel. A
943 "logging channel" indicates an area of an application. Exactly how an
944 "area" is defined is up to the application developer. Since an
945 application can have any number of areas, logging channels are identified
946 by a unique string. Application areas can be nested (e.g. an area
947 of "input processing" might include sub-areas "read CSV files", "read
948 XLS files" and "read Gnumeric files"). To cater for this natural nesting,
949 channel names are organized into a namespace hierarchy where levels are
950 separated by periods, much like the Java or Python package namespace. So
951 in the instance given above, channel names might be "input" for the upper
952 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
953 There is no arbitrary limit to the depth of nesting.
955 def __init__(self
, name
, level
=NOTSET
):
957 Initialize the logger with a name and an optional level.
959 Filterer
.__init
__(self
)
967 def setLevel(self
, level
):
969 Set the logging level of this logger.
973 def debug(self
, msg
, *args
, **kwargs
):
975 Log 'msg % args' with severity 'DEBUG'.
977 To pass exception information, use the keyword argument exc_info with
980 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
982 if self
.isEnabledFor(DEBUG
):
983 apply(self
._log
, (DEBUG
, msg
, args
), kwargs
)
985 def info(self
, msg
, *args
, **kwargs
):
987 Log 'msg % args' with severity 'INFO'.
989 To pass exception information, use the keyword argument exc_info with
992 logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
994 if self
.isEnabledFor(INFO
):
995 apply(self
._log
, (INFO
, msg
, args
), kwargs
)
997 def warning(self
, msg
, *args
, **kwargs
):
999 Log 'msg % args' with severity 'WARNING'.
1001 To pass exception information, use the keyword argument exc_info with
1004 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
1006 if self
.isEnabledFor(WARNING
):
1007 apply(self
._log
, (WARNING
, msg
, args
), kwargs
)
1011 def error(self
, msg
, *args
, **kwargs
):
1013 Log 'msg % args' with severity 'ERROR'.
1015 To pass exception information, use the keyword argument exc_info with
1018 logger.error("Houston, we have a %s", "major problem", exc_info=1)
1020 if self
.isEnabledFor(ERROR
):
1021 apply(self
._log
, (ERROR
, msg
, args
), kwargs
)
1023 def exception(self
, msg
, *args
):
1025 Convenience method for logging an ERROR with exception information.
1027 apply(self
.error
, (msg
,) + args
, {'exc_info': 1})
1029 def critical(self
, msg
, *args
, **kwargs
):
1031 Log 'msg % args' with severity 'CRITICAL'.
1033 To pass exception information, use the keyword argument exc_info with
1036 logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
1038 if self
.isEnabledFor(CRITICAL
):
1039 apply(self
._log
, (CRITICAL
, msg
, args
), kwargs
)
1043 def log(self
, level
, msg
, *args
, **kwargs
):
1045 Log 'msg % args' with the integer severity 'level'.
1047 To pass exception information, use the keyword argument exc_info with
1050 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1052 if type(level
) != types
.IntType
:
1054 raise TypeError, "level must be an integer"
1057 if self
.isEnabledFor(level
):
1058 apply(self
._log
, (level
, msg
, args
), kwargs
)
1060 def findCaller(self
):
1062 Find the stack frame of the caller so that we can note the source
1063 file name, line number and function name.
1065 f
= currentframe().f_back
1066 rv
= "(unknown file)", 0, "(unknown function)"
1067 while hasattr(f
, "f_code"):
1069 filename
= os
.path
.normcase(co
.co_filename
)
1070 if filename
== _srcfile
:
1073 rv
= (filename
, f
.f_lineno
, co
.co_name
)
1077 def makeRecord(self
, name
, level
, fn
, lno
, msg
, args
, exc_info
, func
=None, extra
=None):
1079 A factory method which can be overridden in subclasses to create
1080 specialized LogRecords.
1082 rv
= LogRecord(name
, level
, fn
, lno
, msg
, args
, exc_info
, func
)
1083 if extra
is not None:
1085 if (key
in ["message", "asctime"]) or (key
in rv
.__dict
__):
1086 raise KeyError("Attempt to overwrite %r in LogRecord" % key
)
1087 rv
.__dict
__[key
] = extra
[key
]
1090 def _log(self
, level
, msg
, args
, exc_info
=None, extra
=None):
1092 Low-level logging routine which creates a LogRecord and then calls
1093 all the handlers of this logger to handle the record.
1096 fn
, lno
, func
= self
.findCaller()
1098 fn
, lno
, func
= "(unknown file)", 0, "(unknown function)"
1100 if type(exc_info
) != types
.TupleType
:
1101 exc_info
= sys
.exc_info()
1102 record
= self
.makeRecord(self
.name
, level
, fn
, lno
, msg
, args
, exc_info
, func
, extra
)
1105 def handle(self
, record
):
1107 Call the handlers for the specified record.
1109 This method is used for unpickled records received from a socket, as
1110 well as those created locally. Logger-level filtering is applied.
1112 if (not self
.disabled
) and self
.filter(record
):
1113 self
.callHandlers(record
)
1115 def addHandler(self
, hdlr
):
1117 Add the specified handler to this logger.
1119 if not (hdlr
in self
.handlers
):
1120 self
.handlers
.append(hdlr
)
1122 def removeHandler(self
, hdlr
):
1124 Remove the specified handler from this logger.
1126 if hdlr
in self
.handlers
:
1130 self
.handlers
.remove(hdlr
)
1134 def callHandlers(self
, record
):
1136 Pass a record to all relevant handlers.
1138 Loop through all handlers for this logger and its parents in the
1139 logger hierarchy. If no handler was found, output a one-off error
1140 message to sys.stderr. Stop searching up the hierarchy whenever a
1141 logger with the "propagate" attribute set to zero is found - that
1142 will be the last logger whose handlers are called.
1147 for hdlr
in c
.handlers
:
1149 if record
.levelno
>= hdlr
.level
:
1155 if (found
== 0) and raiseExceptions
and not self
.manager
.emittedNoHandlerWarning
:
1156 sys
.stderr
.write("No handlers could be found for logger"
1157 " \"%s\"\n" % self
.name
)
1158 self
.manager
.emittedNoHandlerWarning
= 1
1160 def getEffectiveLevel(self
):
1162 Get the effective level for this logger.
1164 Loop through this logger and its parents in the logger hierarchy,
1165 looking for a non-zero logging level. Return the first one found.
1171 logger
= logger
.parent
1174 def isEnabledFor(self
, level
):
1176 Is this logger enabled for level 'level'?
1178 if self
.manager
.disable
>= level
:
1180 return level
>= self
.getEffectiveLevel()
1182 class RootLogger(Logger
):
1184 A root logger is not that different to any other logger, except that
1185 it must have a logging level and there is only one instance of it in
1188 def __init__(self
, level
):
1190 Initialize the logger with the name "root".
1192 Logger
.__init
__(self
, "root", level
)
1194 _loggerClass
= Logger
1196 class LoggerAdapter
:
1198 An adapter for loggers which makes it easier to specify contextual
1199 information in logging output.
1202 def __init__(self
, logger
, extra
):
1204 Initialize the adapter with a logger and a dict-like object which
1205 provides contextual information. This constructor signature allows
1206 easy stacking of LoggerAdapters, if so desired.
1208 You can effectively pass keyword arguments as shown in the
1211 adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
1213 self
.logger
= logger
1216 def process(self
, msg
, kwargs
):
1218 Process the logging message and keyword arguments passed in to
1219 a logging call to insert contextual information. You can either
1220 manipulate the message itself, the keyword args or both. Return
1221 the message and kwargs modified (or not) to suit your needs.
1223 Normally, you'll only need to override this one method in a
1224 LoggerAdapter subclass for your specific needs.
1226 kwargs
["extra"] = self
.extra
1229 def debug(self
, msg
, *args
, **kwargs
):
1231 Delegate a debug call to the underlying logger, after adding
1232 contextual information from this adapter instance.
1234 msg
, kwargs
= self
.process(msg
, kwargs
)
1235 self
.logger
.debug(msg
, *args
, **kwargs
)
1237 def info(self
, msg
, *args
, **kwargs
):
1239 Delegate an info call to the underlying logger, after adding
1240 contextual information from this adapter instance.
1242 msg
, kwargs
= self
.process(msg
, kwargs
)
1243 self
.logger
.info(msg
, *args
, **kwargs
)
1245 def warning(self
, msg
, *args
, **kwargs
):
1247 Delegate a warning call to the underlying logger, after adding
1248 contextual information from this adapter instance.
1250 msg
, kwargs
= self
.process(msg
, kwargs
)
1251 self
.logger
.warning(msg
, *args
, **kwargs
)
1253 def error(self
, msg
, *args
, **kwargs
):
1255 Delegate an error call to the underlying logger, after adding
1256 contextual information from this adapter instance.
1258 msg
, kwargs
= self
.process(msg
, kwargs
)
1259 self
.logger
.error(msg
, *args
, **kwargs
)
1261 def exception(self
, msg
, *args
, **kwargs
):
1263 Delegate an exception call to the underlying logger, after adding
1264 contextual information from this adapter instance.
1266 msg
, kwargs
= self
.process(msg
, kwargs
)
1267 kwargs
["exc_info"] = 1
1268 self
.logger
.error(msg
, *args
, **kwargs
)
1270 def critical(self
, msg
, *args
, **kwargs
):
1272 Delegate a critical call to the underlying logger, after adding
1273 contextual information from this adapter instance.
1275 msg
, kwargs
= self
.process(msg
, kwargs
)
1276 self
.logger
.critical(msg
, *args
, **kwargs
)
1278 def log(self
, level
, msg
, *args
, **kwargs
):
1280 Delegate a log call to the underlying logger, after adding
1281 contextual information from this adapter instance.
1283 msg
, kwargs
= self
.process(msg
, kwargs
)
1284 self
.logger
.log(level
, msg
, *args
, **kwargs
)
1286 root
= RootLogger(WARNING
)
1288 Logger
.manager
= Manager(Logger
.root
)
1290 #---------------------------------------------------------------------------
1291 # Configuration classes and functions
1292 #---------------------------------------------------------------------------
1294 BASIC_FORMAT
= "%(levelname)s:%(name)s:%(message)s"
1296 def basicConfig(**kwargs
):
1298 Do basic configuration for the logging system.
1300 This function does nothing if the root logger already has handlers
1301 configured. It is a convenience method intended for use by simple scripts
1302 to do one-shot configuration of the logging package.
1304 The default behaviour is to create a StreamHandler which writes to
1305 sys.stderr, set a formatter using the BASIC_FORMAT format string, and
1306 add the handler to the root logger.
1308 A number of optional keyword arguments may be specified, which can alter
1309 the default behaviour.
1311 filename Specifies that a FileHandler be created, using the specified
1312 filename, rather than a StreamHandler.
1313 filemode Specifies the mode to open the file, if filename is specified
1314 (if filemode is unspecified, it defaults to 'a').
1315 format Use the specified format string for the handler.
1316 datefmt Use the specified date/time format.
1317 level Set the root logger level to the specified level.
1318 stream Use the specified stream to initialize the StreamHandler. Note
1319 that this argument is incompatible with 'filename' - if both
1320 are present, 'stream' is ignored.
1322 Note that you could specify a stream created using open(filename, mode)
1323 rather than passing the filename and mode in. However, it should be
1324 remembered that StreamHandler does not close its stream (since it may be
1325 using sys.stdout or sys.stderr), whereas FileHandler closes its stream
1326 when the handler is closed.
1328 if len(root
.handlers
) == 0:
1329 filename
= kwargs
.get("filename")
1331 mode
= kwargs
.get("filemode", 'a')
1332 hdlr
= FileHandler(filename
, mode
)
1334 stream
= kwargs
.get("stream")
1335 hdlr
= StreamHandler(stream
)
1336 fs
= kwargs
.get("format", BASIC_FORMAT
)
1337 dfs
= kwargs
.get("datefmt", None)
1338 fmt
= Formatter(fs
, dfs
)
1339 hdlr
.setFormatter(fmt
)
1340 root
.addHandler(hdlr
)
1341 level
= kwargs
.get("level")
1342 if level
is not None:
1343 root
.setLevel(level
)
1345 #---------------------------------------------------------------------------
1346 # Utility functions at module level.
1347 # Basically delegate everything to the root logger.
1348 #---------------------------------------------------------------------------
1350 def getLogger(name
=None):
1352 Return a logger with the specified name, creating it if necessary.
1354 If no name is specified, return the root logger.
1357 return Logger
.manager
.getLogger(name
)
1361 #def getRootLogger():
1363 # Return the root logger.
1365 # Note that getLogger('') now does the same thing, so this function is
1366 # deprecated and may disappear in the future.
1370 def critical(msg
, *args
, **kwargs
):
1372 Log a message with severity 'CRITICAL' on the root logger.
1374 if len(root
.handlers
) == 0:
1376 apply(root
.critical
, (msg
,)+args
, kwargs
)
1380 def error(msg
, *args
, **kwargs
):
1382 Log a message with severity 'ERROR' on the root logger.
1384 if len(root
.handlers
) == 0:
1386 apply(root
.error
, (msg
,)+args
, kwargs
)
1388 def exception(msg
, *args
):
1390 Log a message with severity 'ERROR' on the root logger,
1391 with exception information.
1393 apply(error
, (msg
,)+args
, {'exc_info': 1})
1395 def warning(msg
, *args
, **kwargs
):
1397 Log a message with severity 'WARNING' on the root logger.
1399 if len(root
.handlers
) == 0:
1401 apply(root
.warning
, (msg
,)+args
, kwargs
)
1405 def info(msg
, *args
, **kwargs
):
1407 Log a message with severity 'INFO' on the root logger.
1409 if len(root
.handlers
) == 0:
1411 apply(root
.info
, (msg
,)+args
, kwargs
)
1413 def debug(msg
, *args
, **kwargs
):
1415 Log a message with severity 'DEBUG' on the root logger.
1417 if len(root
.handlers
) == 0:
1419 apply(root
.debug
, (msg
,)+args
, kwargs
)
1421 def log(level
, msg
, *args
, **kwargs
):
1423 Log 'msg % args' with the integer severity 'level' on the root logger.
1425 if len(root
.handlers
) == 0:
1427 apply(root
.log
, (level
, msg
)+args
, kwargs
)
1431 Disable all logging calls less severe than 'level'.
1433 root
.manager
.disable
= level
1435 def shutdown(handlerList
=_handlerList
):
1437 Perform any cleanup actions in the logging system (e.g. flushing
1440 Should be called at application exit.
1442 for h
in handlerList
[:]:
1443 #errors might occur, for example, if files are locked
1444 #we just ignore them if raiseExceptions is not set
1453 #Let's try and shutdown automatically on application exit...
1456 atexit
.register(shutdown
)
1457 except ImportError: # for Python versions < 2.0
1458 def exithook(status
, old_exit
=sys
.exit
):