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 import sys
, os
, time
, cStringIO
, traceback
, warnings
28 __all__
= ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
29 'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO',
30 'LogRecord', 'Logger', 'LoggerAdapter', 'NOTSET', 'NullHandler',
31 'StreamHandler', 'WARN', 'WARNING', 'addLevelName', 'basicConfig',
32 'captureWarnings', 'critical', 'debug', 'disable', 'error',
33 'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass',
34 'info', 'log', 'makeLogRecord', 'setLoggerClass', 'warn', 'warning']
47 __author__
= "Vinay Sajip <vinay_sajip@red-dove.com>"
48 __status__
= "production"
49 __version__
= "0.5.0.9"
50 __date__
= "09 October 2009"
52 #---------------------------------------------------------------------------
53 # Miscellaneous module data
54 #---------------------------------------------------------------------------
62 # _srcfile is used when walking the stack to check when we've got the first
65 if hasattr(sys
, 'frozen'): #support for py2exe
66 _srcfile
= "logging%s__init__%s" % (os
.sep
, __file__
[-4:])
67 elif __file__
[-4:].lower() in ['.pyc', '.pyo']:
68 _srcfile
= __file__
[:-4] + '.py'
71 _srcfile
= os
.path
.normcase(_srcfile
)
73 # next bit filched from 1.5.2's inspect.py
75 """Return the frame object for the caller's stack frame."""
79 return sys
.exc_info()[2].tb_frame
.f_back
81 if hasattr(sys
, '_getframe'): currentframe
= lambda: sys
._getframe
(3)
84 # _srcfile is only used in conjunction with sys._getframe().
85 # To provide compatibility with older versions of Python, set _srcfile
86 # to None if _getframe() is not available; this value will prevent
87 # findCaller() from being called.
88 #if not hasattr(sys, "_getframe"):
92 #_startTime is used as the base when calculating the relative time of events
94 _startTime
= time
.time()
97 #raiseExceptions is used to see if exceptions during handling should be
103 # If you don't want threading information in the log, set this to zero
108 # If you don't want multiprocessing information in the log, set this to zero
110 logMultiprocessing
= 1
113 # If you don't want process information in the log, set this to zero
117 #---------------------------------------------------------------------------
118 # Level related stuff
119 #---------------------------------------------------------------------------
121 # Default levels and level names, these can be replaced with any positive set
122 # of values having corresponding names. There is a pseudo-level, NOTSET, which
123 # is only really there as a lower limit for user-defined levels. Handlers and
124 # loggers are initialized with NOTSET so that they will log all messages, even
125 # at user-defined levels.
138 CRITICAL
: 'CRITICAL',
144 'CRITICAL' : CRITICAL
,
153 def getLevelName(level
):
155 Return the textual representation of logging level 'level'.
157 If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
158 INFO, DEBUG) then you get the corresponding string. If you have
159 associated levels with names using addLevelName then the name you have
160 associated with 'level' is returned.
162 If a numeric value corresponding to one of the defined levels is passed
163 in, the corresponding string representation is returned.
165 Otherwise, the string "Level %s" % level is returned.
167 return _levelNames
.get(level
, ("Level %s" % level
))
169 def addLevelName(level
, levelName
):
171 Associate 'levelName' with 'level'.
173 This is used when converting levels to text during message formatting.
176 try: #unlikely to cause an exception, but you never know...
177 _levelNames
[level
] = levelName
178 _levelNames
[levelName
] = level
182 def _checkLevel(level
):
183 if isinstance(level
, int):
185 elif str(level
) == level
:
186 if level
not in _levelNames
:
187 raise ValueError("Unknown level: %r" % level
)
188 rv
= _levelNames
[level
]
190 raise TypeError("Level not an integer or a valid string: %r" % level
)
193 #---------------------------------------------------------------------------
194 # Thread-related stuff
195 #---------------------------------------------------------------------------
198 #_lock is used to serialize access to shared data structures in this module.
199 #This needs to be an RLock because fileConfig() creates Handlers and so
200 #might arbitrary user threads. Since Handler.__init__() updates the shared
201 #dictionary _handlers, it needs to acquire the lock. But if configuring,
202 #the lock would already have been acquired - so we need an RLock.
203 #The same argument applies to Loggers and Manager.loggerDict.
209 Acquire the module-level lock for serializing access to shared data.
211 This should be released with _releaseLock().
214 if (not _lock
) and thread
:
215 _lock
= threading
.RLock()
221 Release the module-level lock acquired by calling _acquireLock().
226 #---------------------------------------------------------------------------
228 #---------------------------------------------------------------------------
232 A LogRecord instance represents an event being logged.
234 LogRecord instances are created every time something is logged. They
235 contain all the information pertinent to the event being logged. The
236 main information passed in is in msg and args, which are combined
237 using str(msg) % args to create the message field of the record. The
238 record also includes information such as when the record was created,
239 the source line where the logging call was made, and any exception
240 information to be logged.
242 def __init__(self
, name
, level
, pathname
, lineno
,
243 msg
, args
, exc_info
, func
=None):
245 Initialize a logging record with interesting information.
251 # The following statement allows passing of a dictionary as a sole
252 # argument, so that you can do something like
253 # logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2})
254 # Suggested by Stefan Behnel.
255 # Note that without the test for args[0], we get a problem because
256 # during formatting, we test to see if the arg is present using
257 # 'if self.args:'. If the event being logged is e.g. 'Value is %d'
258 # and if the passed arg fails 'if self.args:' then no formatting
259 # is done. For example, logger.warn('Value is %d', 0) would log
260 # 'Value is %d' instead of 'Value is 0'.
261 # For the use case of passing a dictionary, this should not be a
263 if args
and len(args
) == 1 and isinstance(args
[0], dict) and args
[0]:
266 self
.levelname
= getLevelName(level
)
268 self
.pathname
= pathname
270 self
.filename
= os
.path
.basename(pathname
)
271 self
.module
= os
.path
.splitext(self
.filename
)[0]
272 except (TypeError, ValueError, AttributeError):
273 self
.filename
= pathname
274 self
.module
= "Unknown module"
275 self
.exc_info
= exc_info
276 self
.exc_text
= None # used to cache the traceback text
280 self
.msecs
= (ct
- long(ct
)) * 1000
281 self
.relativeCreated
= (self
.created
- _startTime
) * 1000
282 if logThreads
and thread
:
283 self
.thread
= thread
.get_ident()
284 self
.threadName
= threading
.current_thread().name
287 self
.threadName
= None
288 if not logMultiprocessing
:
289 self
.processName
= None
290 elif 'multiprocessing' not in sys
.modules
:
291 self
.processName
= 'MainProcess'
293 self
.processName
= sys
.modules
['multiprocessing'].current_process().name
294 if logProcesses
and hasattr(os
, 'getpid'):
295 self
.process
= os
.getpid()
300 return '<LogRecord: %s, %s, %s, %s, "%s">'%(self
.name
, self
.levelno
,
301 self
.pathname
, self
.lineno
, self
.msg
)
303 def getMessage(self
):
305 Return the message for this LogRecord.
307 Return the message for this LogRecord after merging any user-supplied
308 arguments with the message.
310 if not _unicode
: #if no unicode support...
314 if not isinstance(msg
, basestring
):
318 msg
= self
.msg
#Defer encoding till later
320 msg
= msg
% self
.args
323 def makeLogRecord(dict):
325 Make a LogRecord whose attributes are defined by the specified dictionary,
326 This function is useful for converting a logging event received over
327 a socket connection (which is sent as a dictionary) into a LogRecord
330 rv
= LogRecord(None, None, "", 0, "", (), None, None)
331 rv
.__dict
__.update(dict)
334 #---------------------------------------------------------------------------
335 # Formatter classes and functions
336 #---------------------------------------------------------------------------
340 Formatter instances are used to convert a LogRecord to text.
342 Formatters need to know how a LogRecord is constructed. They are
343 responsible for converting a LogRecord to (usually) a string which can
344 be interpreted by either a human or an external system. The base Formatter
345 allows a formatting string to be specified. If none is supplied, the
346 default value of "%s(message)\\n" is used.
348 The Formatter can be initialized with a format string which makes use of
349 knowledge of the LogRecord attributes - e.g. the default value mentioned
350 above makes use of the fact that the user's message and arguments are pre-
351 formatted into a LogRecord's message attribute. Currently, the useful
352 attributes in a LogRecord are described by:
354 %(name)s Name of the logger (logging channel)
355 %(levelno)s Numeric logging level for the message (DEBUG, INFO,
356 WARNING, ERROR, CRITICAL)
357 %(levelname)s Text logging level for the message ("DEBUG", "INFO",
358 "WARNING", "ERROR", "CRITICAL")
359 %(pathname)s Full pathname of the source file where the logging
360 call was issued (if available)
361 %(filename)s Filename portion of pathname
362 %(module)s Module (name portion of filename)
363 %(lineno)d Source line number where the logging call was issued
365 %(funcName)s Function name
366 %(created)f Time when the LogRecord was created (time.time()
368 %(asctime)s Textual time when the LogRecord was created
369 %(msecs)d Millisecond portion of the creation time
370 %(relativeCreated)d Time in milliseconds when the LogRecord was created,
371 relative to the time the logging module was loaded
372 (typically at application startup time)
373 %(thread)d Thread ID (if available)
374 %(threadName)s Thread name (if available)
375 %(process)d Process ID (if available)
376 %(message)s The result of record.getMessage(), computed just as
377 the record is emitted
380 converter
= time
.localtime
382 def __init__(self
, fmt
=None, datefmt
=None):
384 Initialize the formatter with specified format strings.
386 Initialize the formatter either with the specified format string, or a
387 default as described above. Allow for specialized date formatting with
388 the optional datefmt argument (if omitted, you get the ISO8601 format).
393 self
._fmt
= "%(message)s"
394 self
.datefmt
= datefmt
396 def formatTime(self
, record
, datefmt
=None):
398 Return the creation time of the specified LogRecord as formatted text.
400 This method should be called from format() by a formatter which
401 wants to make use of a formatted time. This method can be overridden
402 in formatters to provide for any specific requirement, but the
403 basic behaviour is as follows: if datefmt (a string) is specified,
404 it is used with time.strftime() to format the creation time of the
405 record. Otherwise, the ISO8601 format is used. The resulting
406 string is returned. This function uses a user-configurable function
407 to convert the creation time to a tuple. By default, time.localtime()
408 is used; to change this for a particular formatter instance, set the
409 'converter' attribute to a function with the same signature as
410 time.localtime() or time.gmtime(). To change it for all formatters,
411 for example if you want all logging times to be shown in GMT,
412 set the 'converter' attribute in the Formatter class.
414 ct
= self
.converter(record
.created
)
416 s
= time
.strftime(datefmt
, ct
)
418 t
= time
.strftime("%Y-%m-%d %H:%M:%S", ct
)
419 s
= "%s,%03d" % (t
, record
.msecs
)
422 def formatException(self
, ei
):
424 Format and return the specified exception information as a string.
426 This default implementation just uses
427 traceback.print_exception()
429 sio
= cStringIO
.StringIO()
430 traceback
.print_exception(ei
[0], ei
[1], ei
[2], None, sio
)
437 def format(self
, record
):
439 Format the specified record as text.
441 The record's attribute dictionary is used as the operand to a
442 string formatting operation which yields the returned string.
443 Before formatting the dictionary, a couple of preparatory steps
444 are carried out. The message attribute of the record is computed
445 using LogRecord.getMessage(). If the formatting string contains
446 "%(asctime)", formatTime() is called to format the event time.
447 If there is exception information, it is formatted using
448 formatException() and appended to the message.
450 record
.message
= record
.getMessage()
451 if self
._fmt
.find("%(asctime)") >= 0:
452 record
.asctime
= self
.formatTime(record
, self
.datefmt
)
453 s
= self
._fmt
% record
.__dict
__
455 # Cache the traceback text to avoid converting it multiple times
456 # (it's constant anyway)
457 if not record
.exc_text
:
458 record
.exc_text
= self
.formatException(record
.exc_info
)
462 s
= s
+ record
.exc_text
466 # The default formatter to use when no other is specified
468 _defaultFormatter
= Formatter()
470 class BufferingFormatter
:
472 A formatter suitable for formatting a number of records.
474 def __init__(self
, linefmt
=None):
476 Optionally specify a formatter which will be used to format each
480 self
.linefmt
= linefmt
482 self
.linefmt
= _defaultFormatter
484 def formatHeader(self
, records
):
486 Return the header string for the specified records.
490 def formatFooter(self
, records
):
492 Return the footer string for the specified records.
496 def format(self
, records
):
498 Format the specified records and return the result as a string.
502 rv
= rv
+ self
.formatHeader(records
)
503 for record
in records
:
504 rv
= rv
+ self
.linefmt
.format(record
)
505 rv
= rv
+ self
.formatFooter(records
)
508 #---------------------------------------------------------------------------
509 # Filter classes and functions
510 #---------------------------------------------------------------------------
514 Filter instances are used to perform arbitrary filtering of LogRecords.
516 Loggers and Handlers can optionally use Filter instances to filter
517 records as desired. The base filter class only allows events which are
518 below a certain point in the logger hierarchy. For example, a filter
519 initialized with "A.B" will allow events logged by loggers "A.B",
520 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
521 initialized with the empty string, all events are passed.
523 def __init__(self
, name
=''):
527 Initialize with the name of the logger which, together with its
528 children, will have its events allowed through the filter. If no
529 name is specified, allow every event.
532 self
.nlen
= len(name
)
534 def filter(self
, record
):
536 Determine if the specified record is to be logged.
538 Is the specified record to be logged? Returns 0 for no, nonzero for
539 yes. If deemed appropriate, the record may be modified in-place.
543 elif self
.name
== record
.name
:
545 elif record
.name
.find(self
.name
, 0, self
.nlen
) != 0:
547 return (record
.name
[self
.nlen
] == ".")
551 A base class for loggers and handlers which allows them to share
556 Initialize the list of filters to be an empty list.
560 def addFilter(self
, filter):
562 Add the specified filter to this handler.
564 if not (filter in self
.filters
):
565 self
.filters
.append(filter)
567 def removeFilter(self
, filter):
569 Remove the specified filter from this handler.
571 if filter in self
.filters
:
572 self
.filters
.remove(filter)
574 def filter(self
, record
):
576 Determine if a record is loggable by consulting all the filters.
578 The default is to allow the record to be logged; any filter can veto
579 this and the record is then dropped. Returns a zero value if a record
580 is to be dropped, else non-zero.
583 for f
in self
.filters
:
584 if not f
.filter(record
):
589 #---------------------------------------------------------------------------
590 # Handler classes and functions
591 #---------------------------------------------------------------------------
593 _handlers
= {} #repository of handlers (for flushing when shutdown called)
594 _handlerList
= [] # added to allow handlers to be removed in reverse of order initialized
596 class Handler(Filterer
):
598 Handler instances dispatch logging events to specific destinations.
600 The base handler class. Acts as a placeholder which defines the Handler
601 interface. Handlers can optionally use Formatter instances to format
602 records as desired. By default, no formatter is specified; in this case,
603 the 'raw' message as determined by record.message is logged.
605 def __init__(self
, level
=NOTSET
):
607 Initializes the instance - basically setting the formatter to None
608 and the filter list to empty.
610 Filterer
.__init
__(self
)
611 self
.level
= _checkLevel(level
)
612 self
.formatter
= None
613 #get the module data lock, as we're updating a shared structure.
615 try: #unlikely to raise an exception, but you never know...
617 _handlerList
.insert(0, self
)
622 def createLock(self
):
624 Acquire a thread lock for serializing access to the underlying I/O.
627 self
.lock
= threading
.RLock()
633 Acquire the I/O thread lock.
640 Release the I/O thread lock.
645 def setLevel(self
, level
):
647 Set the logging level of this handler.
649 self
.level
= _checkLevel(level
)
651 def format(self
, record
):
653 Format the specified record.
655 If a formatter is set, use it. Otherwise, use the default formatter
661 fmt
= _defaultFormatter
662 return fmt
.format(record
)
664 def emit(self
, record
):
666 Do whatever it takes to actually log the specified logging record.
668 This version is intended to be implemented by subclasses and so
669 raises a NotImplementedError.
671 raise NotImplementedError('emit must be implemented '
672 'by Handler subclasses')
674 def handle(self
, record
):
676 Conditionally emit the specified logging record.
678 Emission depends on filters which may have been added to the handler.
679 Wrap the actual emission of the record with acquisition/release of
680 the I/O thread lock. Returns whether the filter passed the record for
683 rv
= self
.filter(record
)
692 def setFormatter(self
, fmt
):
694 Set the formatter for this handler.
700 Ensure all logging output has been flushed.
702 This version does nothing and is intended to be implemented by
709 Tidy up any resources used by the handler.
711 This version does removes the handler from an internal list
712 of handlers which is closed when shutdown() is called. Subclasses
713 should ensure that this gets called from overridden close()
716 #get the module data lock, as we're updating a shared structure.
718 try: #unlikely to raise an exception, but you never know...
720 _handlerList
.remove(self
)
724 def handleError(self
, record
):
726 Handle errors which occur during an emit() call.
728 This method should be called from handlers when an exception is
729 encountered during an emit() call. If raiseExceptions is false,
730 exceptions get silently ignored. This is what is mostly wanted
731 for a logging system - most users will not care about errors in
732 the logging system, they are more interested in application errors.
733 You could, however, replace this with a custom handler if you wish.
734 The record which was being processed is passed in to this method.
739 traceback
.print_exception(ei
[0], ei
[1], ei
[2], None, sys
.stderr
)
741 pass # see issue 5971
745 class StreamHandler(Handler
):
747 A handler class which writes logging records, appropriately formatted,
748 to a stream. Note that this class does not close the stream, as
749 sys.stdout or sys.stderr may be used.
752 def __init__(self
, stream
=None):
754 Initialize the handler.
756 If stream is not specified, sys.stderr is used.
758 Handler
.__init
__(self
)
767 if self
.stream
and hasattr(self
.stream
, "flush"):
770 def emit(self
, record
):
774 If a formatter is specified, it is used to format the record.
775 The record is then written to the stream with a trailing newline. If
776 exception information is present, it is formatted using
777 traceback.print_exception and appended to the stream. If the stream
778 has an 'encoding' attribute, it is used to determine how to do the
779 output to the stream.
782 msg
= self
.format(record
)
785 if not _unicode
: #if no unicode support...
786 stream
.write(fs
% msg
)
789 if (isinstance(msg
, unicode) and
790 getattr(stream
, 'encoding', None)):
791 fs
= fs
.decode(stream
.encoding
)
793 stream
.write(fs
% msg
)
794 except UnicodeEncodeError:
795 #Printing to terminals sometimes fails. For example,
796 #with an encoding of 'cp1251', the above write will
797 #work if written to a stream opened or wrapped by
798 #the codecs module, but fail when writing to a
799 #terminal even when the codepage is set to cp1251.
800 #An extra encoding step seems to be needed.
801 stream
.write((fs
% msg
).encode(stream
.encoding
))
803 stream
.write(fs
% msg
)
805 stream
.write(fs
% msg
.encode("UTF-8"))
807 except (KeyboardInterrupt, SystemExit):
810 self
.handleError(record
)
812 class FileHandler(StreamHandler
):
814 A handler class which writes formatted logging records to disk files.
816 def __init__(self
, filename
, mode
='a', encoding
=None, delay
=0):
818 Open the specified file and use it as the stream for logging.
820 #keep the absolute path, otherwise derived classes which use this
821 #may come a cropper when the current directory changes
824 self
.baseFilename
= os
.path
.abspath(filename
)
826 self
.encoding
= encoding
828 #We don't open the stream, but we still need to call the
829 #Handler constructor to set level, formatter, lock etc.
830 Handler
.__init
__(self
)
833 StreamHandler
.__init
__(self
, self
._open
())
841 if hasattr(self
.stream
, "close"):
843 StreamHandler
.close(self
)
848 Open the current base file with the (original) mode and encoding.
849 Return the resulting stream.
851 if self
.encoding
is None:
852 stream
= open(self
.baseFilename
, self
.mode
)
854 stream
= codecs
.open(self
.baseFilename
, self
.mode
, self
.encoding
)
857 def emit(self
, record
):
861 If the stream was not opened because 'delay' was specified in the
862 constructor, open it before calling the superclass's emit.
864 if self
.stream
is None:
865 self
.stream
= self
._open
()
866 StreamHandler
.emit(self
, record
)
868 #---------------------------------------------------------------------------
869 # Manager classes and functions
870 #---------------------------------------------------------------------------
874 PlaceHolder instances are used in the Manager logger hierarchy to take
875 the place of nodes for which no loggers have been defined. This class is
876 intended for internal use only and not as part of the public API.
878 def __init__(self
, alogger
):
880 Initialize with the specified logger being a child of this placeholder.
882 #self.loggers = [alogger]
883 self
.loggerMap
= { alogger
: None }
885 def append(self
, alogger
):
887 Add the specified logger as a child of this placeholder.
889 #if alogger not in self.loggers:
890 if alogger
not in self
.loggerMap
:
891 #self.loggers.append(alogger)
892 self
.loggerMap
[alogger
] = None
895 # Determine which class to use when instantiating loggers.
899 def setLoggerClass(klass
):
901 Set the class to be used when instantiating a logger. The class should
902 define __init__() such that only a name argument is required, and the
903 __init__() should call Logger.__init__()
906 if not issubclass(klass
, Logger
):
907 raise TypeError("logger not derived from logging.Logger: "
912 def getLoggerClass():
914 Return the class to be used when instantiating a logger.
921 There is [under normal circumstances] just one Manager instance, which
922 holds the hierarchy of loggers.
924 def __init__(self
, rootnode
):
926 Initialize the manager with the root node of the logger hierarchy.
930 self
.emittedNoHandlerWarning
= 0
933 def getLogger(self
, name
):
935 Get a logger with the specified name (channel name), creating it
936 if it doesn't yet exist. This name is a dot-separated hierarchical
937 name, such as "a", "a.b", "a.b.c" or similar.
939 If a PlaceHolder existed for the specified name [i.e. the logger
940 didn't exist but a child of it did], replace it with the created
941 logger and fix up the parent/child references which pointed to the
942 placeholder to now point to the logger.
947 if name
in self
.loggerDict
:
948 rv
= self
.loggerDict
[name
]
949 if isinstance(rv
, PlaceHolder
):
951 rv
= _loggerClass(name
)
953 self
.loggerDict
[name
] = rv
954 self
._fixupChildren
(ph
, rv
)
955 self
._fixupParents
(rv
)
957 rv
= _loggerClass(name
)
959 self
.loggerDict
[name
] = rv
960 self
._fixupParents
(rv
)
965 def _fixupParents(self
, alogger
):
967 Ensure that there are either loggers or placeholders all the way
968 from the specified logger to the root of the logger hierarchy.
973 while (i
> 0) and not rv
:
975 if substr
not in self
.loggerDict
:
976 self
.loggerDict
[substr
] = PlaceHolder(alogger
)
978 obj
= self
.loggerDict
[substr
]
979 if isinstance(obj
, Logger
):
982 assert isinstance(obj
, PlaceHolder
)
984 i
= name
.rfind(".", 0, i
- 1)
989 def _fixupChildren(self
, ph
, alogger
):
991 Ensure that children of the placeholder ph are connected to the
996 for c
in ph
.loggerMap
.keys():
997 #The if means ... if not c.parent.name.startswith(nm)
998 if c
.parent
.name
[:namelen
] != name
:
999 alogger
.parent
= c
.parent
1002 #---------------------------------------------------------------------------
1003 # Logger classes and functions
1004 #---------------------------------------------------------------------------
1006 class Logger(Filterer
):
1008 Instances of the Logger class represent a single logging channel. A
1009 "logging channel" indicates an area of an application. Exactly how an
1010 "area" is defined is up to the application developer. Since an
1011 application can have any number of areas, logging channels are identified
1012 by a unique string. Application areas can be nested (e.g. an area
1013 of "input processing" might include sub-areas "read CSV files", "read
1014 XLS files" and "read Gnumeric files"). To cater for this natural nesting,
1015 channel names are organized into a namespace hierarchy where levels are
1016 separated by periods, much like the Java or Python package namespace. So
1017 in the instance given above, channel names might be "input" for the upper
1018 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
1019 There is no arbitrary limit to the depth of nesting.
1021 def __init__(self
, name
, level
=NOTSET
):
1023 Initialize the logger with a name and an optional level.
1025 Filterer
.__init
__(self
)
1027 self
.level
= _checkLevel(level
)
1033 def setLevel(self
, level
):
1035 Set the logging level of this logger.
1037 self
.level
= _checkLevel(level
)
1039 def debug(self
, msg
, *args
, **kwargs
):
1041 Log 'msg % args' with severity 'DEBUG'.
1043 To pass exception information, use the keyword argument exc_info with
1046 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
1048 if self
.isEnabledFor(DEBUG
):
1049 self
._log
(DEBUG
, msg
, args
, **kwargs
)
1051 def info(self
, msg
, *args
, **kwargs
):
1053 Log 'msg % args' with severity 'INFO'.
1055 To pass exception information, use the keyword argument exc_info with
1058 logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
1060 if self
.isEnabledFor(INFO
):
1061 self
._log
(INFO
, msg
, args
, **kwargs
)
1063 def warning(self
, msg
, *args
, **kwargs
):
1065 Log 'msg % args' with severity 'WARNING'.
1067 To pass exception information, use the keyword argument exc_info with
1070 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
1072 if self
.isEnabledFor(WARNING
):
1073 self
._log
(WARNING
, msg
, args
, **kwargs
)
1077 def error(self
, msg
, *args
, **kwargs
):
1079 Log 'msg % args' with severity 'ERROR'.
1081 To pass exception information, use the keyword argument exc_info with
1084 logger.error("Houston, we have a %s", "major problem", exc_info=1)
1086 if self
.isEnabledFor(ERROR
):
1087 self
._log
(ERROR
, msg
, args
, **kwargs
)
1089 def exception(self
, msg
, *args
):
1091 Convenience method for logging an ERROR with exception information.
1093 self
.error(msg
, exc_info
=1, *args
)
1095 def critical(self
, msg
, *args
, **kwargs
):
1097 Log 'msg % args' with severity 'CRITICAL'.
1099 To pass exception information, use the keyword argument exc_info with
1102 logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
1104 if self
.isEnabledFor(CRITICAL
):
1105 self
._log
(CRITICAL
, msg
, args
, **kwargs
)
1109 def log(self
, level
, msg
, *args
, **kwargs
):
1111 Log 'msg % args' with the integer severity 'level'.
1113 To pass exception information, use the keyword argument exc_info with
1116 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1118 if not isinstance(level
, int):
1120 raise TypeError("level must be an integer")
1123 if self
.isEnabledFor(level
):
1124 self
._log
(level
, msg
, args
, **kwargs
)
1126 def findCaller(self
):
1128 Find the stack frame of the caller so that we can note the source
1129 file name, line number and function name.
1132 #On some versions of IronPython, currentframe() returns None if
1133 #IronPython isn't run with -X:Frames.
1136 rv
= "(unknown file)", 0, "(unknown function)"
1137 while hasattr(f
, "f_code"):
1139 filename
= os
.path
.normcase(co
.co_filename
)
1140 if filename
== _srcfile
:
1143 rv
= (filename
, f
.f_lineno
, co
.co_name
)
1147 def makeRecord(self
, name
, level
, fn
, lno
, msg
, args
, exc_info
, func
=None, extra
=None):
1149 A factory method which can be overridden in subclasses to create
1150 specialized LogRecords.
1152 rv
= LogRecord(name
, level
, fn
, lno
, msg
, args
, exc_info
, func
)
1153 if extra
is not None:
1155 if (key
in ["message", "asctime"]) or (key
in rv
.__dict
__):
1156 raise KeyError("Attempt to overwrite %r in LogRecord" % key
)
1157 rv
.__dict
__[key
] = extra
[key
]
1160 def _log(self
, level
, msg
, args
, exc_info
=None, extra
=None):
1162 Low-level logging routine which creates a LogRecord and then calls
1163 all the handlers of this logger to handle the record.
1166 #IronPython doesn't track Python frames, so findCaller throws an
1167 #exception on some versions of IronPython. We trap it here so that
1168 #IronPython can use logging.
1170 fn
, lno
, func
= self
.findCaller()
1172 fn
, lno
, func
= "(unknown file)", 0, "(unknown function)"
1174 fn
, lno
, func
= "(unknown file)", 0, "(unknown function)"
1176 if not isinstance(exc_info
, tuple):
1177 exc_info
= sys
.exc_info()
1178 record
= self
.makeRecord(self
.name
, level
, fn
, lno
, msg
, args
, exc_info
, func
, extra
)
1181 def handle(self
, record
):
1183 Call the handlers for the specified record.
1185 This method is used for unpickled records received from a socket, as
1186 well as those created locally. Logger-level filtering is applied.
1188 if (not self
.disabled
) and self
.filter(record
):
1189 self
.callHandlers(record
)
1191 def addHandler(self
, hdlr
):
1193 Add the specified handler to this logger.
1195 if not (hdlr
in self
.handlers
):
1196 self
.handlers
.append(hdlr
)
1198 def removeHandler(self
, hdlr
):
1200 Remove the specified handler from this logger.
1202 if hdlr
in self
.handlers
:
1206 self
.handlers
.remove(hdlr
)
1210 def callHandlers(self
, record
):
1212 Pass a record to all relevant handlers.
1214 Loop through all handlers for this logger and its parents in the
1215 logger hierarchy. If no handler was found, output a one-off error
1216 message to sys.stderr. Stop searching up the hierarchy whenever a
1217 logger with the "propagate" attribute set to zero is found - that
1218 will be the last logger whose handlers are called.
1223 for hdlr
in c
.handlers
:
1225 if record
.levelno
>= hdlr
.level
:
1231 if (found
== 0) and raiseExceptions
and not self
.manager
.emittedNoHandlerWarning
:
1232 sys
.stderr
.write("No handlers could be found for logger"
1233 " \"%s\"\n" % self
.name
)
1234 self
.manager
.emittedNoHandlerWarning
= 1
1236 def getEffectiveLevel(self
):
1238 Get the effective level for this logger.
1240 Loop through this logger and its parents in the logger hierarchy,
1241 looking for a non-zero logging level. Return the first one found.
1247 logger
= logger
.parent
1250 def isEnabledFor(self
, level
):
1252 Is this logger enabled for level 'level'?
1254 if self
.manager
.disable
>= level
:
1256 return level
>= self
.getEffectiveLevel()
1258 class RootLogger(Logger
):
1260 A root logger is not that different to any other logger, except that
1261 it must have a logging level and there is only one instance of it in
1264 def __init__(self
, level
):
1266 Initialize the logger with the name "root".
1268 Logger
.__init
__(self
, "root", level
)
1270 _loggerClass
= Logger
1272 class LoggerAdapter
:
1274 An adapter for loggers which makes it easier to specify contextual
1275 information in logging output.
1278 def __init__(self
, logger
, extra
):
1280 Initialize the adapter with a logger and a dict-like object which
1281 provides contextual information. This constructor signature allows
1282 easy stacking of LoggerAdapters, if so desired.
1284 You can effectively pass keyword arguments as shown in the
1287 adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
1289 self
.logger
= logger
1292 def process(self
, msg
, kwargs
):
1294 Process the logging message and keyword arguments passed in to
1295 a logging call to insert contextual information. You can either
1296 manipulate the message itself, the keyword args or both. Return
1297 the message and kwargs modified (or not) to suit your needs.
1299 Normally, you'll only need to override this one method in a
1300 LoggerAdapter subclass for your specific needs.
1302 kwargs
["extra"] = self
.extra
1305 def debug(self
, msg
, *args
, **kwargs
):
1307 Delegate a debug call to the underlying logger, after adding
1308 contextual information from this adapter instance.
1310 msg
, kwargs
= self
.process(msg
, kwargs
)
1311 self
.logger
.debug(msg
, *args
, **kwargs
)
1313 def info(self
, msg
, *args
, **kwargs
):
1315 Delegate an info call to the underlying logger, after adding
1316 contextual information from this adapter instance.
1318 msg
, kwargs
= self
.process(msg
, kwargs
)
1319 self
.logger
.info(msg
, *args
, **kwargs
)
1321 def warning(self
, msg
, *args
, **kwargs
):
1323 Delegate a warning call to the underlying logger, after adding
1324 contextual information from this adapter instance.
1326 msg
, kwargs
= self
.process(msg
, kwargs
)
1327 self
.logger
.warning(msg
, *args
, **kwargs
)
1329 def error(self
, msg
, *args
, **kwargs
):
1331 Delegate an error call to the underlying logger, after adding
1332 contextual information from this adapter instance.
1334 msg
, kwargs
= self
.process(msg
, kwargs
)
1335 self
.logger
.error(msg
, *args
, **kwargs
)
1337 def exception(self
, msg
, *args
, **kwargs
):
1339 Delegate an exception call to the underlying logger, after adding
1340 contextual information from this adapter instance.
1342 msg
, kwargs
= self
.process(msg
, kwargs
)
1343 kwargs
["exc_info"] = 1
1344 self
.logger
.error(msg
, *args
, **kwargs
)
1346 def critical(self
, msg
, *args
, **kwargs
):
1348 Delegate a critical call to the underlying logger, after adding
1349 contextual information from this adapter instance.
1351 msg
, kwargs
= self
.process(msg
, kwargs
)
1352 self
.logger
.critical(msg
, *args
, **kwargs
)
1354 def log(self
, level
, msg
, *args
, **kwargs
):
1356 Delegate a log call to the underlying logger, after adding
1357 contextual information from this adapter instance.
1359 msg
, kwargs
= self
.process(msg
, kwargs
)
1360 self
.logger
.log(level
, msg
, *args
, **kwargs
)
1362 root
= RootLogger(WARNING
)
1364 Logger
.manager
= Manager(Logger
.root
)
1366 #---------------------------------------------------------------------------
1367 # Configuration classes and functions
1368 #---------------------------------------------------------------------------
1370 BASIC_FORMAT
= "%(levelname)s:%(name)s:%(message)s"
1372 def basicConfig(**kwargs
):
1374 Do basic configuration for the logging system.
1376 This function does nothing if the root logger already has handlers
1377 configured. It is a convenience method intended for use by simple scripts
1378 to do one-shot configuration of the logging package.
1380 The default behaviour is to create a StreamHandler which writes to
1381 sys.stderr, set a formatter using the BASIC_FORMAT format string, and
1382 add the handler to the root logger.
1384 A number of optional keyword arguments may be specified, which can alter
1385 the default behaviour.
1387 filename Specifies that a FileHandler be created, using the specified
1388 filename, rather than a StreamHandler.
1389 filemode Specifies the mode to open the file, if filename is specified
1390 (if filemode is unspecified, it defaults to 'a').
1391 format Use the specified format string for the handler.
1392 datefmt Use the specified date/time format.
1393 level Set the root logger level to the specified level.
1394 stream Use the specified stream to initialize the StreamHandler. Note
1395 that this argument is incompatible with 'filename' - if both
1396 are present, 'stream' is ignored.
1398 Note that you could specify a stream created using open(filename, mode)
1399 rather than passing the filename and mode in. However, it should be
1400 remembered that StreamHandler does not close its stream (since it may be
1401 using sys.stdout or sys.stderr), whereas FileHandler closes its stream
1402 when the handler is closed.
1404 if len(root
.handlers
) == 0:
1405 filename
= kwargs
.get("filename")
1407 mode
= kwargs
.get("filemode", 'a')
1408 hdlr
= FileHandler(filename
, mode
)
1410 stream
= kwargs
.get("stream")
1411 hdlr
= StreamHandler(stream
)
1412 fs
= kwargs
.get("format", BASIC_FORMAT
)
1413 dfs
= kwargs
.get("datefmt", None)
1414 fmt
= Formatter(fs
, dfs
)
1415 hdlr
.setFormatter(fmt
)
1416 root
.addHandler(hdlr
)
1417 level
= kwargs
.get("level")
1418 if level
is not None:
1419 root
.setLevel(level
)
1421 #---------------------------------------------------------------------------
1422 # Utility functions at module level.
1423 # Basically delegate everything to the root logger.
1424 #---------------------------------------------------------------------------
1426 def getLogger(name
=None):
1428 Return a logger with the specified name, creating it if necessary.
1430 If no name is specified, return the root logger.
1433 return Logger
.manager
.getLogger(name
)
1437 #def getRootLogger():
1439 # Return the root logger.
1441 # Note that getLogger('') now does the same thing, so this function is
1442 # deprecated and may disappear in the future.
1446 def critical(msg
, *args
, **kwargs
):
1448 Log a message with severity 'CRITICAL' on the root logger.
1450 if len(root
.handlers
) == 0:
1452 root
.critical(msg
, *args
, **kwargs
)
1456 def error(msg
, *args
, **kwargs
):
1458 Log a message with severity 'ERROR' on the root logger.
1460 if len(root
.handlers
) == 0:
1462 root
.error(msg
, *args
, **kwargs
)
1464 def exception(msg
, *args
):
1466 Log a message with severity 'ERROR' on the root logger,
1467 with exception information.
1469 error(msg
, exc_info
=1, *args
)
1471 def warning(msg
, *args
, **kwargs
):
1473 Log a message with severity 'WARNING' on the root logger.
1475 if len(root
.handlers
) == 0:
1477 root
.warning(msg
, *args
, **kwargs
)
1481 def info(msg
, *args
, **kwargs
):
1483 Log a message with severity 'INFO' on the root logger.
1485 if len(root
.handlers
) == 0:
1487 root
.info(msg
, *args
, **kwargs
)
1489 def debug(msg
, *args
, **kwargs
):
1491 Log a message with severity 'DEBUG' on the root logger.
1493 if len(root
.handlers
) == 0:
1495 root
.debug(msg
, *args
, **kwargs
)
1497 def log(level
, msg
, *args
, **kwargs
):
1499 Log 'msg % args' with the integer severity 'level' on the root logger.
1501 if len(root
.handlers
) == 0:
1503 root
.log(level
, msg
, *args
, **kwargs
)
1507 Disable all logging calls less severe than 'level'.
1509 root
.manager
.disable
= level
1511 def shutdown(handlerList
=_handlerList
):
1513 Perform any cleanup actions in the logging system (e.g. flushing
1516 Should be called at application exit.
1518 for h
in handlerList
[:]:
1519 #errors might occur, for example, if files are locked
1520 #we just ignore them if raiseExceptions is not set
1529 #Let's try and shutdown automatically on application exit...
1532 atexit
.register(shutdown
)
1533 except ImportError: # for Python versions < 2.0
1534 def exithook(status
, old_exit
=sys
.exit
):
1544 class NullHandler(Handler
):
1546 This handler does nothing. It's intended to be used to avoid the
1547 "No handlers could be found for logger XXX" one-off warning. This is
1548 important for library code, which may contain code to log events. If a user
1549 of the library does not configure logging, the one-off warning might be
1550 produced; to avoid this, the library developer simply needs to instantiate
1551 a NullHandler and add it to the top-level logger of the library module or
1554 def emit(self
, record
):
1557 # Warnings integration
1559 _warnings_showwarning
= None
1561 def _showwarning(message
, category
, filename
, lineno
, file=None, line
=None):
1563 Implementation of showwarnings which redirects to logging, which will first
1564 check to see if the file parameter is None. If a file is specified, it will
1565 delegate to the original warnings implementation of showwarning. Otherwise,
1566 it will call warnings.formatwarning and will log the resulting string to a
1567 warnings logger named "py.warnings" with level logging.WARNING.
1569 if file is not None:
1570 if _warnings_showwarning
is not None:
1571 _warnings_showwarning(message
, category
, filename
, lineno
, file, line
)
1573 s
= warnings
.formatwarning(message
, category
, filename
, lineno
, line
)
1574 logger
= getLogger("py.warnings")
1575 if not logger
.handlers
:
1576 logger
.addHandler(NullHandler())
1577 logger
.warning("%s", s
)
1579 def captureWarnings(capture
):
1581 If capture is true, redirect all warnings to the logging package.
1582 If capture is False, ensure that warnings are not redirected to logging
1583 but to their original destinations.
1585 global _warnings_showwarning
1587 if _warnings_showwarning
is None:
1588 _warnings_showwarning
= warnings
.showwarning
1589 warnings
.showwarning
= _showwarning
1591 if _warnings_showwarning
is not None:
1592 warnings
.showwarning
= _warnings_showwarning
1593 _warnings_showwarning
= None