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.
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!
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
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
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'
63 _srcfile
= os
.path
.normcase(_srcfile
)
65 # next bit filched from 1.5.2's inspect.py
67 """Return the frame object for the caller's stack frame."""
71 return sys
.exc_traceback
.tb_frame
.f_back
73 if hasattr(sys
, '_getframe'): currentframe
= lambda: sys
._getframe
(3)
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"):
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
95 # If you don't want threading information in the log, set this to zero
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
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.
130 CRITICAL
: 'CRITICAL',
136 'CRITICAL' : CRITICAL
,
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.
168 try: #unlikely to cause an exception, but you never know...
169 _levelNames
[level
] = levelName
170 _levelNames
[levelName
] = level
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.
190 Acquire the module-level lock for serializing access to shared data.
192 This should be released with _releaseLock().
195 if (not _lock
) and thread
:
196 _lock
= threading
.RLock()
202 Release the module-level lock acquired by calling _acquireLock().
207 #---------------------------------------------------------------------------
209 #---------------------------------------------------------------------------
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.
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
244 if args
and len(args
) == 1 and (
245 type(args
[0]) == types
.DictType
249 self
.levelname
= getLevelName(level
)
251 self
.pathname
= pathname
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
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
270 self
.threadName
= None
271 if logMultiprocessing
:
272 from multiprocessing
import current_process
273 self
.processName
= current_process().name
275 self
.processName
= None
276 if logProcesses
and hasattr(os
, 'getpid'):
277 self
.process
= os
.getpid()
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...
296 if type(msg
) not in (types
.UnicodeType
, types
.StringType
):
300 msg
= self
.msg
#Defer encoding till later
302 msg
= msg
% self
.args
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
312 rv
= LogRecord(None, None, "", 0, "", (), None, None)
313 rv
.__dict
__.update(dict)
316 #---------------------------------------------------------------------------
317 # Formatter classes and functions
318 #---------------------------------------------------------------------------
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
347 %(funcName)s Function name
348 %(created)f Time when the LogRecord was created (time.time()
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).
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
)
398 s
= time
.strftime(datefmt
, ct
)
400 t
= time
.strftime("%Y-%m-%d %H:%M:%S", ct
)
401 s
= "%s,%03d" % (t
, record
.msecs
)
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
)
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
__
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
)
444 s
= s
+ record
.exc_text
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
462 self
.linefmt
= linefmt
464 self
.linefmt
= _defaultFormatter
466 def formatHeader(self
, records
):
468 Return the header string for the specified records.
472 def formatFooter(self
, records
):
474 Return the footer string for the specified records.
478 def format(self
, records
):
480 Format the specified records and return the result as a string.
484 rv
= rv
+ self
.formatHeader(records
)
485 for record
in records
:
486 rv
= rv
+ self
.linefmt
.format(record
)
487 rv
= rv
+ self
.formatFooter(records
)
490 #---------------------------------------------------------------------------
491 # Filter classes and functions
492 #---------------------------------------------------------------------------
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
=''):
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.
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.
525 elif self
.name
== record
.name
:
527 elif string
.find(record
.name
, self
.name
, 0, self
.nlen
) != 0:
529 return (record
.name
[self
.nlen
] == ".")
533 A base class for loggers and handlers which allows them to share
538 Initialize the list of filters to be an empty list.
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.
565 for f
in self
.filters
:
566 if not f
.filter(record
):
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
)
594 self
.formatter
= None
595 #get the module data lock, as we're updating a shared structure.
597 try: #unlikely to raise an exception, but you never know...
599 _handlerList
.insert(0, self
)
604 def createLock(self
):
606 Acquire a thread lock for serializing access to the underlying I/O.
609 self
.lock
= threading
.RLock()
615 Acquire the I/O thread lock.
622 Release the I/O thread lock.
627 def setLevel(self
, level
):
629 Set the logging level of this handler.
633 def format(self
, record
):
635 Format the specified record.
637 If a formatter is set, use it. Otherwise, use the default formatter
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
665 rv
= self
.filter(record
)
674 def setFormatter(self
, fmt
):
676 Set the formatter for this handler.
682 Ensure all logging output has been flushed.
684 This version does nothing and is intended to be implemented by
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()
698 #get the module data lock, as we're updating a shared structure.
700 try: #unlikely to raise an exception, but you never know...
702 _handlerList
.remove(self
)
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.
720 traceback
.print_exception(ei
[0], ei
[1], ei
[2], None, sys
.stderr
)
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
)
745 if self
.stream
and hasattr(self
.stream
, "flush"):
748 def emit(self
, 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.
760 msg
= self
.format(record
)
763 if not hasattr(types
, "UnicodeType"): #if no unicode support...
764 stream
.write(fs
% msg
)
767 if (isinstance(msg
, unicode) or
768 getattr(stream
, 'encoding', None) is None):
769 stream
.write(fs
% msg
)
771 stream
.write(fs
% msg
.encode(stream
.encoding
))
773 stream
.write(fs
% msg
.encode("UTF-8"))
775 except (KeyboardInterrupt, SystemExit):
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
792 self
.baseFilename
= os
.path
.abspath(filename
)
794 self
.encoding
= encoding
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
)
801 StreamHandler
.__init
__(self
, self
._open
())
809 if hasattr(self
.stream
, "close"):
811 StreamHandler
.close(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
)
822 stream
= codecs
.open(self
.baseFilename
, self
.mode
, self
.encoding
)
825 def emit(self
, 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 #---------------------------------------------------------------------------
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.
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__()
874 if not issubclass(klass
, Logger
):
875 raise TypeError, "logger not derived from logging.Logger: " + \
880 def getLoggerClass():
882 Return the class to be used when instantiating a logger.
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.
898 self
.emittedNoHandlerWarning
= 0
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.
915 if name
in self
.loggerDict
:
916 rv
= self
.loggerDict
[name
]
917 if isinstance(rv
, PlaceHolder
):
919 rv
= _loggerClass(name
)
921 self
.loggerDict
[name
] = rv
922 self
._fixupChildren
(ph
, rv
)
923 self
._fixupParents
(rv
)
925 rv
= _loggerClass(name
)
927 self
.loggerDict
[name
] = rv
928 self
._fixupParents
(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.
939 i
= string
.rfind(name
, ".")
941 while (i
> 0) and not rv
:
943 if substr
not in self
.loggerDict
:
944 self
.loggerDict
[substr
] = PlaceHolder(alogger
)
946 obj
= self
.loggerDict
[substr
]
947 if isinstance(obj
, Logger
):
950 assert isinstance(obj
, PlaceHolder
)
952 i
= string
.rfind(name
, ".", 0, i
- 1)
957 def _fixupChildren(self
, ph
, alogger
):
959 Ensure that children of the placeholder ph are connected to the
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
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
)
1002 def setLevel(self
, level
):
1004 Set the logging level of this logger.
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
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
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
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
)
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
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
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
)
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
1085 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1087 if type(level
) != types
.IntType
:
1089 raise TypeError, "level must be an integer"
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"):
1104 filename
= os
.path
.normcase(co
.co_filename
)
1105 if filename
== _srcfile
:
1108 rv
= (filename
, f
.f_lineno
, co
.co_name
)
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:
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
]
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.
1131 #IronPython doesn't track Python frames, so findCaller throws an
1132 #exception. We trap it here so that IronPython can use logging.
1134 fn
, lno
, func
= self
.findCaller()
1136 fn
, lno
, func
= "(unknown file)", 0, "(unknown function)"
1138 fn
, lno
, func
= "(unknown file)", 0, "(unknown function)"
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
)
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
:
1170 self
.handlers
.remove(hdlr
)
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.
1187 for hdlr
in c
.handlers
:
1189 if record
.levelno
>= hdlr
.level
:
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.
1211 logger
= logger
.parent
1214 def isEnabledFor(self
, level
):
1216 Is this logger enabled for level 'level'?
1218 if self
.manager
.disable
>= level
:
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
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
1251 adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
1253 self
.logger
= logger
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
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
)
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")
1371 mode
= kwargs
.get("filemode", 'a')
1372 hdlr
= FileHandler(filename
, mode
)
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.
1397 return Logger
.manager
.getLogger(name
)
1401 #def getRootLogger():
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.
1410 def critical(msg
, *args
, **kwargs
):
1412 Log a message with severity 'CRITICAL' on the root logger.
1414 if len(root
.handlers
) == 0:
1416 root
.critical(*((msg
,)+args
), **kwargs
)
1420 def error(msg
, *args
, **kwargs
):
1422 Log a message with severity 'ERROR' on the root logger.
1424 if len(root
.handlers
) == 0:
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:
1441 root
.warning(*((msg
,)+args
), **kwargs
)
1445 def info(msg
, *args
, **kwargs
):
1447 Log a message with severity 'INFO' on the root logger.
1449 if len(root
.handlers
) == 0:
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:
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:
1467 root
.log(*((level
, msg
)+args
), **kwargs
)
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
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
1493 #Let's try and shutdown automatically on application exit...
1496 atexit
.register(shutdown
)
1497 except ImportError: # for Python versions < 2.0
1498 def exithook(status
, old_exit
=sys
.exit
):
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
1518 def emit(self
, record
):
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
)
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
1551 if _warnings_showwarning
is None:
1552 _warnings_showwarning
= warnings
.showwarning
1553 warnings
.showwarning
= _showwarning
1555 if _warnings_showwarning
is not None:
1556 warnings
.showwarning
= _warnings_showwarning
1557 _warnings_showwarning
= None