OILS / opy / _regtest / src / logging / __init__.py View on Github | oilshell.org

1744 lines, 766 significant
1# Copyright 2001-2014 by Vinay Sajip. All Rights Reserved.
2#
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.
16
17"""
18Logging package for Python. Based on PEP 282 and comments thereto in
19comp.lang.python.
20
21Copyright (C) 2001-2014 Vinay Sajip. All Rights Reserved.
22
23To use, simply 'import logging' and log away!
24"""
25
26import sys, os, time, cStringIO, traceback, warnings, weakref, collections
27
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']
35
36try:
37 import codecs
38except ImportError:
39 codecs = None
40
41try:
42 import thread
43 import threading
44except ImportError:
45 thread = None
46
47__author__ = "Vinay Sajip <vinay_sajip@red-dove.com>"
48__status__ = "production"
49# Note: the attributes below are no longer maintained.
50__version__ = "0.5.1.2"
51__date__ = "07 February 2010"
52
53#---------------------------------------------------------------------------
54# Miscellaneous module data
55#---------------------------------------------------------------------------
56try:
57 unicode
58 _unicode = True
59except NameError:
60 _unicode = False
61
62# next bit filched from 1.5.2's inspect.py
63def currentframe():
64 """Return the frame object for the caller's stack frame."""
65 try:
66 raise Exception
67 except:
68 return sys.exc_info()[2].tb_frame.f_back
69
70if hasattr(sys, '_getframe'): currentframe = lambda: sys._getframe(3)
71# done filching
72
73#
74# _srcfile is used when walking the stack to check when we've got the first
75# caller stack frame.
76#
77_srcfile = os.path.normcase(currentframe.__code__.co_filename)
78
79# _srcfile is only used in conjunction with sys._getframe().
80# To provide compatibility with older versions of Python, set _srcfile
81# to None if _getframe() is not available; this value will prevent
82# findCaller() from being called.
83#if not hasattr(sys, "_getframe"):
84# _srcfile = None
85
86#
87#_startTime is used as the base when calculating the relative time of events
88#
89_startTime = time.time()
90
91#
92#raiseExceptions is used to see if exceptions during handling should be
93#propagated
94#
95raiseExceptions = 1
96
97#
98# If you don't want threading information in the log, set this to zero
99#
100logThreads = 1
101
102#
103# If you don't want multiprocessing information in the log, set this to zero
104#
105logMultiprocessing = 1
106
107#
108# If you don't want process information in the log, set this to zero
109#
110logProcesses = 1
111
112#---------------------------------------------------------------------------
113# Level related stuff
114#---------------------------------------------------------------------------
115#
116# Default levels and level names, these can be replaced with any positive set
117# of values having corresponding names. There is a pseudo-level, NOTSET, which
118# is only really there as a lower limit for user-defined levels. Handlers and
119# loggers are initialized with NOTSET so that they will log all messages, even
120# at user-defined levels.
121#
122
123CRITICAL = 50
124FATAL = CRITICAL
125ERROR = 40
126WARNING = 30
127WARN = WARNING
128INFO = 20
129DEBUG = 10
130NOTSET = 0
131
132_levelNames = {
133 CRITICAL : 'CRITICAL',
134 ERROR : 'ERROR',
135 WARNING : 'WARNING',
136 INFO : 'INFO',
137 DEBUG : 'DEBUG',
138 NOTSET : 'NOTSET',
139 'CRITICAL' : CRITICAL,
140 'ERROR' : ERROR,
141 'WARN' : WARNING,
142 'WARNING' : WARNING,
143 'INFO' : INFO,
144 'DEBUG' : DEBUG,
145 'NOTSET' : NOTSET,
146}
147
148def getLevelName(level):
149 """
150 Return the textual representation of logging level 'level'.
151
152 If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
153 INFO, DEBUG) then you get the corresponding string. If you have
154 associated levels with names using addLevelName then the name you have
155 associated with 'level' is returned.
156
157 If a numeric value corresponding to one of the defined levels is passed
158 in, the corresponding string representation is returned.
159
160 Otherwise, the string "Level %s" % level is returned.
161 """
162 return _levelNames.get(level, ("Level %s" % level))
163
164def addLevelName(level, levelName):
165 """
166 Associate 'levelName' with 'level'.
167
168 This is used when converting levels to text during message formatting.
169 """
170 _acquireLock()
171 try: #unlikely to cause an exception, but you never know...
172 _levelNames[level] = levelName
173 _levelNames[levelName] = level
174 finally:
175 _releaseLock()
176
177def _checkLevel(level):
178 if isinstance(level, (int, long)):
179 rv = level
180 elif str(level) == level:
181 if level not in _levelNames:
182 raise ValueError("Unknown level: %r" % level)
183 rv = _levelNames[level]
184 else:
185 raise TypeError("Level not an integer or a valid string: %r" % level)
186 return rv
187
188#---------------------------------------------------------------------------
189# Thread-related stuff
190#---------------------------------------------------------------------------
191
192#
193#_lock is used to serialize access to shared data structures in this module.
194#This needs to be an RLock because fileConfig() creates and configures
195#Handlers, and so might arbitrary user threads. Since Handler code updates the
196#shared dictionary _handlers, it needs to acquire the lock. But if configuring,
197#the lock would already have been acquired - so we need an RLock.
198#The same argument applies to Loggers and Manager.loggerDict.
199#
200if thread:
201 _lock = threading.RLock()
202else:
203 _lock = None
204
205def _acquireLock():
206 """
207 Acquire the module-level lock for serializing access to shared data.
208
209 This should be released with _releaseLock().
210 """
211 if _lock:
212 _lock.acquire()
213
214def _releaseLock():
215 """
216 Release the module-level lock acquired by calling _acquireLock().
217 """
218 if _lock:
219 _lock.release()
220
221#---------------------------------------------------------------------------
222# The logging record
223#---------------------------------------------------------------------------
224
225class LogRecord(object):
226 """
227 A LogRecord instance represents an event being logged.
228
229 LogRecord instances are created every time something is logged. They
230 contain all the information pertinent to the event being logged. The
231 main information passed in is in msg and args, which are combined
232 using str(msg) % args to create the message field of the record. The
233 record also includes information such as when the record was created,
234 the source line where the logging call was made, and any exception
235 information to be logged.
236 """
237 def __init__(self, name, level, pathname, lineno,
238 msg, args, exc_info, func=None):
239 """
240 Initialize a logging record with interesting information.
241 """
242 ct = time.time()
243 self.name = name
244 self.msg = msg
245 #
246 # The following statement allows passing of a dictionary as a sole
247 # argument, so that you can do something like
248 # logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2})
249 # Suggested by Stefan Behnel.
250 # Note that without the test for args[0], we get a problem because
251 # during formatting, we test to see if the arg is present using
252 # 'if self.args:'. If the event being logged is e.g. 'Value is %d'
253 # and if the passed arg fails 'if self.args:' then no formatting
254 # is done. For example, logger.warn('Value is %d', 0) would log
255 # 'Value is %d' instead of 'Value is 0'.
256 # For the use case of passing a dictionary, this should not be a
257 # problem.
258 # Issue #21172: a request was made to relax the isinstance check
259 # to hasattr(args[0], '__getitem__'). However, the docs on string
260 # formatting still seem to suggest a mapping object is required.
261 # Thus, while not removing the isinstance check, it does now look
262 # for collections.Mapping rather than, as before, dict.
263 if (args and len(args) == 1 and isinstance(args[0], collections.Mapping)
264 and args[0]):
265 args = args[0]
266 self.args = args
267 self.levelname = getLevelName(level)
268 self.levelno = level
269 self.pathname = pathname
270 try:
271 self.filename = os.path.basename(pathname)
272 self.module = os.path.splitext(self.filename)[0]
273 except (TypeError, ValueError, AttributeError):
274 self.filename = pathname
275 self.module = "Unknown module"
276 self.exc_info = exc_info
277 self.exc_text = None # used to cache the traceback text
278 self.lineno = lineno
279 self.funcName = func
280 self.created = ct
281 self.msecs = (ct - long(ct)) * 1000
282 self.relativeCreated = (self.created - _startTime) * 1000
283 if logThreads and thread:
284 self.thread = thread.get_ident()
285 self.threadName = threading.current_thread().name
286 else:
287 self.thread = None
288 self.threadName = None
289 if not logMultiprocessing:
290 self.processName = None
291 else:
292 self.processName = 'MainProcess'
293 mp = sys.modules.get('multiprocessing')
294 if mp is not None:
295 # Errors may occur if multiprocessing has not finished loading
296 # yet - e.g. if a custom import hook causes third-party code
297 # to run when multiprocessing calls import. See issue 8200
298 # for an example
299 try:
300 self.processName = mp.current_process().name
301 except StandardError:
302 pass
303 if logProcesses and hasattr(os, 'getpid'):
304 self.process = os.getpid()
305 else:
306 self.process = None
307
308 def __str__(self):
309 return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
310 self.pathname, self.lineno, self.msg)
311
312 def getMessage(self):
313 """
314 Return the message for this LogRecord.
315
316 Return the message for this LogRecord after merging any user-supplied
317 arguments with the message.
318 """
319 if not _unicode: #if no unicode support...
320 msg = str(self.msg)
321 else:
322 msg = self.msg
323 if not isinstance(msg, basestring):
324 try:
325 msg = str(self.msg)
326 except UnicodeError:
327 msg = self.msg #Defer encoding till later
328 if self.args:
329 msg = msg % self.args
330 return msg
331
332def makeLogRecord(dict):
333 """
334 Make a LogRecord whose attributes are defined by the specified dictionary,
335 This function is useful for converting a logging event received over
336 a socket connection (which is sent as a dictionary) into a LogRecord
337 instance.
338 """
339 rv = LogRecord(None, None, "", 0, "", (), None, None)
340 rv.__dict__.update(dict)
341 return rv
342
343#---------------------------------------------------------------------------
344# Formatter classes and functions
345#---------------------------------------------------------------------------
346
347class Formatter(object):
348 """
349 Formatter instances are used to convert a LogRecord to text.
350
351 Formatters need to know how a LogRecord is constructed. They are
352 responsible for converting a LogRecord to (usually) a string which can
353 be interpreted by either a human or an external system. The base Formatter
354 allows a formatting string to be specified. If none is supplied, the
355 default value of "%s(message)\\n" is used.
356
357 The Formatter can be initialized with a format string which makes use of
358 knowledge of the LogRecord attributes - e.g. the default value mentioned
359 above makes use of the fact that the user's message and arguments are pre-
360 formatted into a LogRecord's message attribute. Currently, the useful
361 attributes in a LogRecord are described by:
362
363 %(name)s Name of the logger (logging channel)
364 %(levelno)s Numeric logging level for the message (DEBUG, INFO,
365 WARNING, ERROR, CRITICAL)
366 %(levelname)s Text logging level for the message ("DEBUG", "INFO",
367 "WARNING", "ERROR", "CRITICAL")
368 %(pathname)s Full pathname of the source file where the logging
369 call was issued (if available)
370 %(filename)s Filename portion of pathname
371 %(module)s Module (name portion of filename)
372 %(lineno)d Source line number where the logging call was issued
373 (if available)
374 %(funcName)s Function name
375 %(created)f Time when the LogRecord was created (time.time()
376 return value)
377 %(asctime)s Textual time when the LogRecord was created
378 %(msecs)d Millisecond portion of the creation time
379 %(relativeCreated)d Time in milliseconds when the LogRecord was created,
380 relative to the time the logging module was loaded
381 (typically at application startup time)
382 %(thread)d Thread ID (if available)
383 %(threadName)s Thread name (if available)
384 %(process)d Process ID (if available)
385 %(message)s The result of record.getMessage(), computed just as
386 the record is emitted
387 """
388
389 converter = time.localtime
390
391 def __init__(self, fmt=None, datefmt=None):
392 """
393 Initialize the formatter with specified format strings.
394
395 Initialize the formatter either with the specified format string, or a
396 default as described above. Allow for specialized date formatting with
397 the optional datefmt argument (if omitted, you get the ISO8601 format).
398 """
399 if fmt:
400 self._fmt = fmt
401 else:
402 self._fmt = "%(message)s"
403 self.datefmt = datefmt
404
405 def formatTime(self, record, datefmt=None):
406 """
407 Return the creation time of the specified LogRecord as formatted text.
408
409 This method should be called from format() by a formatter which
410 wants to make use of a formatted time. This method can be overridden
411 in formatters to provide for any specific requirement, but the
412 basic behaviour is as follows: if datefmt (a string) is specified,
413 it is used with time.strftime() to format the creation time of the
414 record. Otherwise, the ISO8601 format is used. The resulting
415 string is returned. This function uses a user-configurable function
416 to convert the creation time to a tuple. By default, time.localtime()
417 is used; to change this for a particular formatter instance, set the
418 'converter' attribute to a function with the same signature as
419 time.localtime() or time.gmtime(). To change it for all formatters,
420 for example if you want all logging times to be shown in GMT,
421 set the 'converter' attribute in the Formatter class.
422 """
423 ct = self.converter(record.created)
424 if datefmt:
425 s = time.strftime(datefmt, ct)
426 else:
427 t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
428 s = "%s,%03d" % (t, record.msecs)
429 return s
430
431 def formatException(self, ei):
432 """
433 Format and return the specified exception information as a string.
434
435 This default implementation just uses
436 traceback.print_exception()
437 """
438 sio = cStringIO.StringIO()
439 traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
440 s = sio.getvalue()
441 sio.close()
442 if s[-1:] == "\n":
443 s = s[:-1]
444 return s
445
446 def usesTime(self):
447 """
448 Check if the format uses the creation time of the record.
449 """
450 return self._fmt.find("%(asctime)") >= 0
451
452 def format(self, record):
453 """
454 Format the specified record as text.
455
456 The record's attribute dictionary is used as the operand to a
457 string formatting operation which yields the returned string.
458 Before formatting the dictionary, a couple of preparatory steps
459 are carried out. The message attribute of the record is computed
460 using LogRecord.getMessage(). If the formatting string uses the
461 time (as determined by a call to usesTime(), formatTime() is
462 called to format the event time. If there is exception information,
463 it is formatted using formatException() and appended to the message.
464 """
465 record.message = record.getMessage()
466 if self.usesTime():
467 record.asctime = self.formatTime(record, self.datefmt)
468 try:
469 s = self._fmt % record.__dict__
470 except UnicodeDecodeError as e:
471 # Issue 25664. The logger name may be Unicode. Try again ...
472 try:
473 record.name = record.name.decode('utf-8')
474 s = self._fmt % record.__dict__
475 except UnicodeDecodeError:
476 raise e
477 if record.exc_info:
478 # Cache the traceback text to avoid converting it multiple times
479 # (it's constant anyway)
480 if not record.exc_text:
481 record.exc_text = self.formatException(record.exc_info)
482 if record.exc_text:
483 if s[-1:] != "\n":
484 s = s + "\n"
485 try:
486 s = s + record.exc_text
487 except UnicodeError:
488 # Sometimes filenames have non-ASCII chars, which can lead
489 # to errors when s is Unicode and record.exc_text is str
490 # See issue 8924.
491 # We also use replace for when there are multiple
492 # encodings, e.g. UTF-8 for the filesystem and latin-1
493 # for a script. See issue 13232.
494 s = s + record.exc_text.decode(sys.getfilesystemencoding(),
495 'replace')
496 return s
497
498#
499# The default formatter to use when no other is specified
500#
501_defaultFormatter = Formatter()
502
503class BufferingFormatter(object):
504 """
505 A formatter suitable for formatting a number of records.
506 """
507 def __init__(self, linefmt=None):
508 """
509 Optionally specify a formatter which will be used to format each
510 individual record.
511 """
512 if linefmt:
513 self.linefmt = linefmt
514 else:
515 self.linefmt = _defaultFormatter
516
517 def formatHeader(self, records):
518 """
519 Return the header string for the specified records.
520 """
521 return ""
522
523 def formatFooter(self, records):
524 """
525 Return the footer string for the specified records.
526 """
527 return ""
528
529 def format(self, records):
530 """
531 Format the specified records and return the result as a string.
532 """
533 rv = ""
534 if len(records) > 0:
535 rv = rv + self.formatHeader(records)
536 for record in records:
537 rv = rv + self.linefmt.format(record)
538 rv = rv + self.formatFooter(records)
539 return rv
540
541#---------------------------------------------------------------------------
542# Filter classes and functions
543#---------------------------------------------------------------------------
544
545class Filter(object):
546 """
547 Filter instances are used to perform arbitrary filtering of LogRecords.
548
549 Loggers and Handlers can optionally use Filter instances to filter
550 records as desired. The base filter class only allows events which are
551 below a certain point in the logger hierarchy. For example, a filter
552 initialized with "A.B" will allow events logged by loggers "A.B",
553 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
554 initialized with the empty string, all events are passed.
555 """
556 def __init__(self, name=''):
557 """
558 Initialize a filter.
559
560 Initialize with the name of the logger which, together with its
561 children, will have its events allowed through the filter. If no
562 name is specified, allow every event.
563 """
564 self.name = name
565 self.nlen = len(name)
566
567 def filter(self, record):
568 """
569 Determine if the specified record is to be logged.
570
571 Is the specified record to be logged? Returns 0 for no, nonzero for
572 yes. If deemed appropriate, the record may be modified in-place.
573 """
574 if self.nlen == 0:
575 return 1
576 elif self.name == record.name:
577 return 1
578 elif record.name.find(self.name, 0, self.nlen) != 0:
579 return 0
580 return (record.name[self.nlen] == ".")
581
582class Filterer(object):
583 """
584 A base class for loggers and handlers which allows them to share
585 common code.
586 """
587 def __init__(self):
588 """
589 Initialize the list of filters to be an empty list.
590 """
591 self.filters = []
592
593 def addFilter(self, filter):
594 """
595 Add the specified filter to this handler.
596 """
597 if not (filter in self.filters):
598 self.filters.append(filter)
599
600 def removeFilter(self, filter):
601 """
602 Remove the specified filter from this handler.
603 """
604 if filter in self.filters:
605 self.filters.remove(filter)
606
607 def filter(self, record):
608 """
609 Determine if a record is loggable by consulting all the filters.
610
611 The default is to allow the record to be logged; any filter can veto
612 this and the record is then dropped. Returns a zero value if a record
613 is to be dropped, else non-zero.
614 """
615 rv = 1
616 for f in self.filters:
617 if not f.filter(record):
618 rv = 0
619 break
620 return rv
621
622#---------------------------------------------------------------------------
623# Handler classes and functions
624#---------------------------------------------------------------------------
625
626_handlers = weakref.WeakValueDictionary() #map of handler names to handlers
627_handlerList = [] # added to allow handlers to be removed in reverse of order initialized
628
629def _removeHandlerRef(wr):
630 """
631 Remove a handler reference from the internal cleanup list.
632 """
633 # This function can be called during module teardown, when globals are
634 # set to None. It can also be called from another thread. So we need to
635 # pre-emptively grab the necessary globals and check if they're None,
636 # to prevent race conditions and failures during interpreter shutdown.
637 acquire, release, handlers = _acquireLock, _releaseLock, _handlerList
638 if acquire and release and handlers:
639 acquire()
640 try:
641 if wr in handlers:
642 handlers.remove(wr)
643 finally:
644 release()
645
646def _addHandlerRef(handler):
647 """
648 Add a handler to the internal cleanup list using a weak reference.
649 """
650 _acquireLock()
651 try:
652 _handlerList.append(weakref.ref(handler, _removeHandlerRef))
653 finally:
654 _releaseLock()
655
656class Handler(Filterer):
657 """
658 Handler instances dispatch logging events to specific destinations.
659
660 The base handler class. Acts as a placeholder which defines the Handler
661 interface. Handlers can optionally use Formatter instances to format
662 records as desired. By default, no formatter is specified; in this case,
663 the 'raw' message as determined by record.message is logged.
664 """
665 def __init__(self, level=NOTSET):
666 """
667 Initializes the instance - basically setting the formatter to None
668 and the filter list to empty.
669 """
670 Filterer.__init__(self)
671 self._name = None
672 self.level = _checkLevel(level)
673 self.formatter = None
674 # Add the handler to the global _handlerList (for cleanup on shutdown)
675 _addHandlerRef(self)
676 self.createLock()
677
678 def get_name(self):
679 return self._name
680
681 def set_name(self, name):
682 _acquireLock()
683 try:
684 if self._name in _handlers:
685 del _handlers[self._name]
686 self._name = name
687 if name:
688 _handlers[name] = self
689 finally:
690 _releaseLock()
691
692 name = property(get_name, set_name)
693
694 def createLock(self):
695 """
696 Acquire a thread lock for serializing access to the underlying I/O.
697 """
698 if thread:
699 self.lock = threading.RLock()
700 else:
701 self.lock = None
702
703 def acquire(self):
704 """
705 Acquire the I/O thread lock.
706 """
707 if self.lock:
708 self.lock.acquire()
709
710 def release(self):
711 """
712 Release the I/O thread lock.
713 """
714 if self.lock:
715 self.lock.release()
716
717 def setLevel(self, level):
718 """
719 Set the logging level of this handler.
720 """
721 self.level = _checkLevel(level)
722
723 def format(self, record):
724 """
725 Format the specified record.
726
727 If a formatter is set, use it. Otherwise, use the default formatter
728 for the module.
729 """
730 if self.formatter:
731 fmt = self.formatter
732 else:
733 fmt = _defaultFormatter
734 return fmt.format(record)
735
736 def emit(self, record):
737 """
738 Do whatever it takes to actually log the specified logging record.
739
740 This version is intended to be implemented by subclasses and so
741 raises a NotImplementedError.
742 """
743 raise NotImplementedError('emit must be implemented '
744 'by Handler subclasses')
745
746 def handle(self, record):
747 """
748 Conditionally emit the specified logging record.
749
750 Emission depends on filters which may have been added to the handler.
751 Wrap the actual emission of the record with acquisition/release of
752 the I/O thread lock. Returns whether the filter passed the record for
753 emission.
754 """
755 rv = self.filter(record)
756 if rv:
757 self.acquire()
758 try:
759 self.emit(record)
760 finally:
761 self.release()
762 return rv
763
764 def setFormatter(self, fmt):
765 """
766 Set the formatter for this handler.
767 """
768 self.formatter = fmt
769
770 def flush(self):
771 """
772 Ensure all logging output has been flushed.
773
774 This version does nothing and is intended to be implemented by
775 subclasses.
776 """
777 pass
778
779 def close(self):
780 """
781 Tidy up any resources used by the handler.
782
783 This version removes the handler from an internal map of handlers,
784 _handlers, which is used for handler lookup by name. Subclasses
785 should ensure that this gets called from overridden close()
786 methods.
787 """
788 #get the module data lock, as we're updating a shared structure.
789 _acquireLock()
790 try: #unlikely to raise an exception, but you never know...
791 if self._name and self._name in _handlers:
792 del _handlers[self._name]
793 finally:
794 _releaseLock()
795
796 def handleError(self, record):
797 """
798 Handle errors which occur during an emit() call.
799
800 This method should be called from handlers when an exception is
801 encountered during an emit() call. If raiseExceptions is false,
802 exceptions get silently ignored. This is what is mostly wanted
803 for a logging system - most users will not care about errors in
804 the logging system, they are more interested in application errors.
805 You could, however, replace this with a custom handler if you wish.
806 The record which was being processed is passed in to this method.
807 """
808 if raiseExceptions and sys.stderr: # see issue 13807
809 ei = sys.exc_info()
810 try:
811 traceback.print_exception(ei[0], ei[1], ei[2],
812 None, sys.stderr)
813 sys.stderr.write('Logged from file %s, line %s\n' % (
814 record.filename, record.lineno))
815 except IOError:
816 pass # see issue 5971
817 finally:
818 del ei
819
820class StreamHandler(Handler):
821 """
822 A handler class which writes logging records, appropriately formatted,
823 to a stream. Note that this class does not close the stream, as
824 sys.stdout or sys.stderr may be used.
825 """
826
827 def __init__(self, stream=None):
828 """
829 Initialize the handler.
830
831 If stream is not specified, sys.stderr is used.
832 """
833 Handler.__init__(self)
834 if stream is None:
835 stream = sys.stderr
836 self.stream = stream
837
838 def flush(self):
839 """
840 Flushes the stream.
841 """
842 self.acquire()
843 try:
844 if self.stream and hasattr(self.stream, "flush"):
845 self.stream.flush()
846 finally:
847 self.release()
848
849 def emit(self, record):
850 """
851 Emit a record.
852
853 If a formatter is specified, it is used to format the record.
854 The record is then written to the stream with a trailing newline. If
855 exception information is present, it is formatted using
856 traceback.print_exception and appended to the stream. If the stream
857 has an 'encoding' attribute, it is used to determine how to do the
858 output to the stream.
859 """
860 try:
861 msg = self.format(record)
862 stream = self.stream
863 fs = "%s\n"
864 if not _unicode: #if no unicode support...
865 stream.write(fs % msg)
866 else:
867 try:
868 if (isinstance(msg, unicode) and
869 getattr(stream, 'encoding', None)):
870 ufs = u'%s\n'
871 try:
872 stream.write(ufs % msg)
873 except UnicodeEncodeError:
874 #Printing to terminals sometimes fails. For example,
875 #with an encoding of 'cp1251', the above write will
876 #work if written to a stream opened or wrapped by
877 #the codecs module, but fail when writing to a
878 #terminal even when the codepage is set to cp1251.
879 #An extra encoding step seems to be needed.
880 stream.write((ufs % msg).encode(stream.encoding))
881 else:
882 stream.write(fs % msg)
883 except UnicodeError:
884 stream.write(fs % msg.encode("UTF-8"))
885 self.flush()
886 except (KeyboardInterrupt, SystemExit):
887 raise
888 except:
889 self.handleError(record)
890
891class FileHandler(StreamHandler):
892 """
893 A handler class which writes formatted logging records to disk files.
894 """
895 def __init__(self, filename, mode='a', encoding=None, delay=0):
896 """
897 Open the specified file and use it as the stream for logging.
898 """
899 #keep the absolute path, otherwise derived classes which use this
900 #may come a cropper when the current directory changes
901 if codecs is None:
902 encoding = None
903 self.baseFilename = os.path.abspath(filename)
904 self.mode = mode
905 self.encoding = encoding
906 self.delay = delay
907 if delay:
908 #We don't open the stream, but we still need to call the
909 #Handler constructor to set level, formatter, lock etc.
910 Handler.__init__(self)
911 self.stream = None
912 else:
913 StreamHandler.__init__(self, self._open())
914
915 def close(self):
916 """
917 Closes the stream.
918 """
919 self.acquire()
920 try:
921 try:
922 if self.stream:
923 try:
924 self.flush()
925 finally:
926 stream = self.stream
927 self.stream = None
928 if hasattr(stream, "close"):
929 stream.close()
930 finally:
931 # Issue #19523: call unconditionally to
932 # prevent a handler leak when delay is set
933 StreamHandler.close(self)
934 finally:
935 self.release()
936
937 def _open(self):
938 """
939 Open the current base file with the (original) mode and encoding.
940 Return the resulting stream.
941 """
942 if self.encoding is None:
943 stream = open(self.baseFilename, self.mode)
944 else:
945 stream = codecs.open(self.baseFilename, self.mode, self.encoding)
946 return stream
947
948 def emit(self, record):
949 """
950 Emit a record.
951
952 If the stream was not opened because 'delay' was specified in the
953 constructor, open it before calling the superclass's emit.
954 """
955 if self.stream is None:
956 self.stream = self._open()
957 StreamHandler.emit(self, record)
958
959#---------------------------------------------------------------------------
960# Manager classes and functions
961#---------------------------------------------------------------------------
962
963class PlaceHolder(object):
964 """
965 PlaceHolder instances are used in the Manager logger hierarchy to take
966 the place of nodes for which no loggers have been defined. This class is
967 intended for internal use only and not as part of the public API.
968 """
969 def __init__(self, alogger):
970 """
971 Initialize with the specified logger being a child of this placeholder.
972 """
973 #self.loggers = [alogger]
974 self.loggerMap = { alogger : None }
975
976 def append(self, alogger):
977 """
978 Add the specified logger as a child of this placeholder.
979 """
980 #if alogger not in self.loggers:
981 if alogger not in self.loggerMap:
982 #self.loggers.append(alogger)
983 self.loggerMap[alogger] = None
984
985#
986# Determine which class to use when instantiating loggers.
987#
988_loggerClass = None
989
990def setLoggerClass(klass):
991 """
992 Set the class to be used when instantiating a logger. The class should
993 define __init__() such that only a name argument is required, and the
994 __init__() should call Logger.__init__()
995 """
996 if klass != Logger:
997 if not issubclass(klass, Logger):
998 raise TypeError("logger not derived from logging.Logger: "
999 + klass.__name__)
1000 global _loggerClass
1001 _loggerClass = klass
1002
1003def getLoggerClass():
1004 """
1005 Return the class to be used when instantiating a logger.
1006 """
1007
1008 return _loggerClass
1009
1010class Manager(object):
1011 """
1012 There is [under normal circumstances] just one Manager instance, which
1013 holds the hierarchy of loggers.
1014 """
1015 def __init__(self, rootnode):
1016 """
1017 Initialize the manager with the root node of the logger hierarchy.
1018 """
1019 self.root = rootnode
1020 self.disable = 0
1021 self.emittedNoHandlerWarning = 0
1022 self.loggerDict = {}
1023 self.loggerClass = None
1024
1025 def getLogger(self, name):
1026 """
1027 Get a logger with the specified name (channel name), creating it
1028 if it doesn't yet exist. This name is a dot-separated hierarchical
1029 name, such as "a", "a.b", "a.b.c" or similar.
1030
1031 If a PlaceHolder existed for the specified name [i.e. the logger
1032 didn't exist but a child of it did], replace it with the created
1033 logger and fix up the parent/child references which pointed to the
1034 placeholder to now point to the logger.
1035 """
1036 rv = None
1037 if not isinstance(name, basestring):
1038 raise TypeError('A logger name must be string or Unicode')
1039 if isinstance(name, unicode):
1040 name = name.encode('utf-8')
1041 _acquireLock()
1042 try:
1043 if name in self.loggerDict:
1044 rv = self.loggerDict[name]
1045 if isinstance(rv, PlaceHolder):
1046 ph = rv
1047 rv = (self.loggerClass or _loggerClass)(name)
1048 rv.manager = self
1049 self.loggerDict[name] = rv
1050 self._fixupChildren(ph, rv)
1051 self._fixupParents(rv)
1052 else:
1053 rv = (self.loggerClass or _loggerClass)(name)
1054 rv.manager = self
1055 self.loggerDict[name] = rv
1056 self._fixupParents(rv)
1057 finally:
1058 _releaseLock()
1059 return rv
1060
1061 def setLoggerClass(self, klass):
1062 """
1063 Set the class to be used when instantiating a logger with this Manager.
1064 """
1065 if klass != Logger:
1066 if not issubclass(klass, Logger):
1067 raise TypeError("logger not derived from logging.Logger: "
1068 + klass.__name__)
1069 self.loggerClass = klass
1070
1071 def _fixupParents(self, alogger):
1072 """
1073 Ensure that there are either loggers or placeholders all the way
1074 from the specified logger to the root of the logger hierarchy.
1075 """
1076 name = alogger.name
1077 i = name.rfind(".")
1078 rv = None
1079 while (i > 0) and not rv:
1080 substr = name[:i]
1081 if substr not in self.loggerDict:
1082 self.loggerDict[substr] = PlaceHolder(alogger)
1083 else:
1084 obj = self.loggerDict[substr]
1085 if isinstance(obj, Logger):
1086 rv = obj
1087 else:
1088 assert isinstance(obj, PlaceHolder)
1089 obj.append(alogger)
1090 i = name.rfind(".", 0, i - 1)
1091 if not rv:
1092 rv = self.root
1093 alogger.parent = rv
1094
1095 def _fixupChildren(self, ph, alogger):
1096 """
1097 Ensure that children of the placeholder ph are connected to the
1098 specified logger.
1099 """
1100 name = alogger.name
1101 namelen = len(name)
1102 for c in ph.loggerMap.keys():
1103 #The if means ... if not c.parent.name.startswith(nm)
1104 if c.parent.name[:namelen] != name:
1105 alogger.parent = c.parent
1106 c.parent = alogger
1107
1108#---------------------------------------------------------------------------
1109# Logger classes and functions
1110#---------------------------------------------------------------------------
1111
1112class Logger(Filterer):
1113 """
1114 Instances of the Logger class represent a single logging channel. A
1115 "logging channel" indicates an area of an application. Exactly how an
1116 "area" is defined is up to the application developer. Since an
1117 application can have any number of areas, logging channels are identified
1118 by a unique string. Application areas can be nested (e.g. an area
1119 of "input processing" might include sub-areas "read CSV files", "read
1120 XLS files" and "read Gnumeric files"). To cater for this natural nesting,
1121 channel names are organized into a namespace hierarchy where levels are
1122 separated by periods, much like the Java or Python package namespace. So
1123 in the instance given above, channel names might be "input" for the upper
1124 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
1125 There is no arbitrary limit to the depth of nesting.
1126 """
1127 def __init__(self, name, level=NOTSET):
1128 """
1129 Initialize the logger with a name and an optional level.
1130 """
1131 Filterer.__init__(self)
1132 self.name = name
1133 self.level = _checkLevel(level)
1134 self.parent = None
1135 self.propagate = 1
1136 self.handlers = []
1137 self.disabled = 0
1138
1139 def setLevel(self, level):
1140 """
1141 Set the logging level of this logger.
1142 """
1143 self.level = _checkLevel(level)
1144
1145 def debug(self, msg, *args, **kwargs):
1146 """
1147 Log 'msg % args' with severity 'DEBUG'.
1148
1149 To pass exception information, use the keyword argument exc_info with
1150 a true value, e.g.
1151
1152 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
1153 """
1154 if self.isEnabledFor(DEBUG):
1155 self._log(DEBUG, msg, args, **kwargs)
1156
1157 def info(self, msg, *args, **kwargs):
1158 """
1159 Log 'msg % args' with severity 'INFO'.
1160
1161 To pass exception information, use the keyword argument exc_info with
1162 a true value, e.g.
1163
1164 logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
1165 """
1166 if self.isEnabledFor(INFO):
1167 self._log(INFO, msg, args, **kwargs)
1168
1169 def warning(self, msg, *args, **kwargs):
1170 """
1171 Log 'msg % args' with severity 'WARNING'.
1172
1173 To pass exception information, use the keyword argument exc_info with
1174 a true value, e.g.
1175
1176 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
1177 """
1178 if self.isEnabledFor(WARNING):
1179 self._log(WARNING, msg, args, **kwargs)
1180
1181 warn = warning
1182
1183 def error(self, msg, *args, **kwargs):
1184 """
1185 Log 'msg % args' with severity 'ERROR'.
1186
1187 To pass exception information, use the keyword argument exc_info with
1188 a true value, e.g.
1189
1190 logger.error("Houston, we have a %s", "major problem", exc_info=1)
1191 """
1192 if self.isEnabledFor(ERROR):
1193 self._log(ERROR, msg, args, **kwargs)
1194
1195 def exception(self, msg, *args, **kwargs):
1196 """
1197 Convenience method for logging an ERROR with exception information.
1198 """
1199 kwargs['exc_info'] = 1
1200 self.error(msg, *args, **kwargs)
1201
1202 def critical(self, msg, *args, **kwargs):
1203 """
1204 Log 'msg % args' with severity 'CRITICAL'.
1205
1206 To pass exception information, use the keyword argument exc_info with
1207 a true value, e.g.
1208
1209 logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
1210 """
1211 if self.isEnabledFor(CRITICAL):
1212 self._log(CRITICAL, msg, args, **kwargs)
1213
1214 fatal = critical
1215
1216 def log(self, level, msg, *args, **kwargs):
1217 """
1218 Log 'msg % args' with the integer severity 'level'.
1219
1220 To pass exception information, use the keyword argument exc_info with
1221 a true value, e.g.
1222
1223 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1224 """
1225 if not isinstance(level, int):
1226 if raiseExceptions:
1227 raise TypeError("level must be an integer")
1228 else:
1229 return
1230 if self.isEnabledFor(level):
1231 self._log(level, msg, args, **kwargs)
1232
1233 def findCaller(self):
1234 """
1235 Find the stack frame of the caller so that we can note the source
1236 file name, line number and function name.
1237 """
1238 f = currentframe()
1239 #On some versions of IronPython, currentframe() returns None if
1240 #IronPython isn't run with -X:Frames.
1241 if f is not None:
1242 f = f.f_back
1243 rv = "(unknown file)", 0, "(unknown function)"
1244 while hasattr(f, "f_code"):
1245 co = f.f_code
1246 filename = os.path.normcase(co.co_filename)
1247 if filename == _srcfile:
1248 f = f.f_back
1249 continue
1250 rv = (co.co_filename, f.f_lineno, co.co_name)
1251 break
1252 return rv
1253
1254 def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None):
1255 """
1256 A factory method which can be overridden in subclasses to create
1257 specialized LogRecords.
1258 """
1259 rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func)
1260 if extra is not None:
1261 for key in extra:
1262 if (key in ["message", "asctime"]) or (key in rv.__dict__):
1263 raise KeyError("Attempt to overwrite %r in LogRecord" % key)
1264 rv.__dict__[key] = extra[key]
1265 return rv
1266
1267 def _log(self, level, msg, args, exc_info=None, extra=None):
1268 """
1269 Low-level logging routine which creates a LogRecord and then calls
1270 all the handlers of this logger to handle the record.
1271 """
1272 if _srcfile:
1273 #IronPython doesn't track Python frames, so findCaller raises an
1274 #exception on some versions of IronPython. We trap it here so that
1275 #IronPython can use logging.
1276 try:
1277 fn, lno, func = self.findCaller()
1278 except ValueError:
1279 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1280 else:
1281 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1282 if exc_info:
1283 if not isinstance(exc_info, tuple):
1284 exc_info = sys.exc_info()
1285 record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra)
1286 self.handle(record)
1287
1288 def handle(self, record):
1289 """
1290 Call the handlers for the specified record.
1291
1292 This method is used for unpickled records received from a socket, as
1293 well as those created locally. Logger-level filtering is applied.
1294 """
1295 if (not self.disabled) and self.filter(record):
1296 self.callHandlers(record)
1297
1298 def addHandler(self, hdlr):
1299 """
1300 Add the specified handler to this logger.
1301 """
1302 _acquireLock()
1303 try:
1304 if not (hdlr in self.handlers):
1305 self.handlers.append(hdlr)
1306 finally:
1307 _releaseLock()
1308
1309 def removeHandler(self, hdlr):
1310 """
1311 Remove the specified handler from this logger.
1312 """
1313 _acquireLock()
1314 try:
1315 if hdlr in self.handlers:
1316 self.handlers.remove(hdlr)
1317 finally:
1318 _releaseLock()
1319
1320 def callHandlers(self, record):
1321 """
1322 Pass a record to all relevant handlers.
1323
1324 Loop through all handlers for this logger and its parents in the
1325 logger hierarchy. If no handler was found, output a one-off error
1326 message to sys.stderr. Stop searching up the hierarchy whenever a
1327 logger with the "propagate" attribute set to zero is found - that
1328 will be the last logger whose handlers are called.
1329 """
1330 c = self
1331 found = 0
1332 while c:
1333 for hdlr in c.handlers:
1334 found = found + 1
1335 if record.levelno >= hdlr.level:
1336 hdlr.handle(record)
1337 if not c.propagate:
1338 c = None #break out
1339 else:
1340 c = c.parent
1341 if (found == 0) and raiseExceptions and not self.manager.emittedNoHandlerWarning:
1342 sys.stderr.write("No handlers could be found for logger"
1343 " \"%s\"\n" % self.name)
1344 self.manager.emittedNoHandlerWarning = 1
1345
1346 def getEffectiveLevel(self):
1347 """
1348 Get the effective level for this logger.
1349
1350 Loop through this logger and its parents in the logger hierarchy,
1351 looking for a non-zero logging level. Return the first one found.
1352 """
1353 logger = self
1354 while logger:
1355 if logger.level:
1356 return logger.level
1357 logger = logger.parent
1358 return NOTSET
1359
1360 def isEnabledFor(self, level):
1361 """
1362 Is this logger enabled for level 'level'?
1363 """
1364 if self.manager.disable >= level:
1365 return 0
1366 return level >= self.getEffectiveLevel()
1367
1368 def getChild(self, suffix):
1369 """
1370 Get a logger which is a descendant to this one.
1371
1372 This is a convenience method, such that
1373
1374 logging.getLogger('abc').getChild('def.ghi')
1375
1376 is the same as
1377
1378 logging.getLogger('abc.def.ghi')
1379
1380 It's useful, for example, when the parent logger is named using
1381 __name__ rather than a literal string.
1382 """
1383 if self.root is not self:
1384 suffix = '.'.join((self.name, suffix))
1385 return self.manager.getLogger(suffix)
1386
1387class RootLogger(Logger):
1388 """
1389 A root logger is not that different to any other logger, except that
1390 it must have a logging level and there is only one instance of it in
1391 the hierarchy.
1392 """
1393 def __init__(self, level):
1394 """
1395 Initialize the logger with the name "root".
1396 """
1397 Logger.__init__(self, "root", level)
1398
1399_loggerClass = Logger
1400
1401class LoggerAdapter(object):
1402 """
1403 An adapter for loggers which makes it easier to specify contextual
1404 information in logging output.
1405 """
1406
1407 def __init__(self, logger, extra):
1408 """
1409 Initialize the adapter with a logger and a dict-like object which
1410 provides contextual information. This constructor signature allows
1411 easy stacking of LoggerAdapters, if so desired.
1412
1413 You can effectively pass keyword arguments as shown in the
1414 following example:
1415
1416 adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
1417 """
1418 self.logger = logger
1419 self.extra = extra
1420
1421 def process(self, msg, kwargs):
1422 """
1423 Process the logging message and keyword arguments passed in to
1424 a logging call to insert contextual information. You can either
1425 manipulate the message itself, the keyword args or both. Return
1426 the message and kwargs modified (or not) to suit your needs.
1427
1428 Normally, you'll only need to override this one method in a
1429 LoggerAdapter subclass for your specific needs.
1430 """
1431 kwargs["extra"] = self.extra
1432 return msg, kwargs
1433
1434 def debug(self, msg, *args, **kwargs):
1435 """
1436 Delegate a debug call to the underlying logger, after adding
1437 contextual information from this adapter instance.
1438 """
1439 msg, kwargs = self.process(msg, kwargs)
1440 self.logger.debug(msg, *args, **kwargs)
1441
1442 def info(self, msg, *args, **kwargs):
1443 """
1444 Delegate an info call to the underlying logger, after adding
1445 contextual information from this adapter instance.
1446 """
1447 msg, kwargs = self.process(msg, kwargs)
1448 self.logger.info(msg, *args, **kwargs)
1449
1450 def warning(self, msg, *args, **kwargs):
1451 """
1452 Delegate a warning call to the underlying logger, after adding
1453 contextual information from this adapter instance.
1454 """
1455 msg, kwargs = self.process(msg, kwargs)
1456 self.logger.warning(msg, *args, **kwargs)
1457
1458 def error(self, msg, *args, **kwargs):
1459 """
1460 Delegate an error call to the underlying logger, after adding
1461 contextual information from this adapter instance.
1462 """
1463 msg, kwargs = self.process(msg, kwargs)
1464 self.logger.error(msg, *args, **kwargs)
1465
1466 def exception(self, msg, *args, **kwargs):
1467 """
1468 Delegate an exception call to the underlying logger, after adding
1469 contextual information from this adapter instance.
1470 """
1471 msg, kwargs = self.process(msg, kwargs)
1472 kwargs["exc_info"] = 1
1473 self.logger.error(msg, *args, **kwargs)
1474
1475 def critical(self, msg, *args, **kwargs):
1476 """
1477 Delegate a critical call to the underlying logger, after adding
1478 contextual information from this adapter instance.
1479 """
1480 msg, kwargs = self.process(msg, kwargs)
1481 self.logger.critical(msg, *args, **kwargs)
1482
1483 def log(self, level, msg, *args, **kwargs):
1484 """
1485 Delegate a log call to the underlying logger, after adding
1486 contextual information from this adapter instance.
1487 """
1488 msg, kwargs = self.process(msg, kwargs)
1489 self.logger.log(level, msg, *args, **kwargs)
1490
1491 def isEnabledFor(self, level):
1492 """
1493 See if the underlying logger is enabled for the specified level.
1494 """
1495 return self.logger.isEnabledFor(level)
1496
1497root = RootLogger(WARNING)
1498Logger.root = root
1499Logger.manager = Manager(Logger.root)
1500
1501#---------------------------------------------------------------------------
1502# Configuration classes and functions
1503#---------------------------------------------------------------------------
1504
1505BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
1506
1507def basicConfig(**kwargs):
1508 """
1509 Do basic configuration for the logging system.
1510
1511 This function does nothing if the root logger already has handlers
1512 configured. It is a convenience method intended for use by simple scripts
1513 to do one-shot configuration of the logging package.
1514
1515 The default behaviour is to create a StreamHandler which writes to
1516 sys.stderr, set a formatter using the BASIC_FORMAT format string, and
1517 add the handler to the root logger.
1518
1519 A number of optional keyword arguments may be specified, which can alter
1520 the default behaviour.
1521
1522 filename Specifies that a FileHandler be created, using the specified
1523 filename, rather than a StreamHandler.
1524 filemode Specifies the mode to open the file, if filename is specified
1525 (if filemode is unspecified, it defaults to 'a').
1526 format Use the specified format string for the handler.
1527 datefmt Use the specified date/time format.
1528 level Set the root logger level to the specified level.
1529 stream Use the specified stream to initialize the StreamHandler. Note
1530 that this argument is incompatible with 'filename' - if both
1531 are present, 'stream' is ignored.
1532
1533 Note that you could specify a stream created using open(filename, mode)
1534 rather than passing the filename and mode in. However, it should be
1535 remembered that StreamHandler does not close its stream (since it may be
1536 using sys.stdout or sys.stderr), whereas FileHandler closes its stream
1537 when the handler is closed.
1538 """
1539 # Add thread safety in case someone mistakenly calls
1540 # basicConfig() from multiple threads
1541 _acquireLock()
1542 try:
1543 if len(root.handlers) == 0:
1544 filename = kwargs.get("filename")
1545 if filename:
1546 mode = kwargs.get("filemode", 'a')
1547 hdlr = FileHandler(filename, mode)
1548 else:
1549 stream = kwargs.get("stream")
1550 hdlr = StreamHandler(stream)
1551 fs = kwargs.get("format", BASIC_FORMAT)
1552 dfs = kwargs.get("datefmt", None)
1553 fmt = Formatter(fs, dfs)
1554 hdlr.setFormatter(fmt)
1555 root.addHandler(hdlr)
1556 level = kwargs.get("level")
1557 if level is not None:
1558 root.setLevel(level)
1559 finally:
1560 _releaseLock()
1561
1562#---------------------------------------------------------------------------
1563# Utility functions at module level.
1564# Basically delegate everything to the root logger.
1565#---------------------------------------------------------------------------
1566
1567def getLogger(name=None):
1568 """
1569 Return a logger with the specified name, creating it if necessary.
1570
1571 If no name is specified, return the root logger.
1572 """
1573 if name:
1574 return Logger.manager.getLogger(name)
1575 else:
1576 return root
1577
1578#def getRootLogger():
1579# """
1580# Return the root logger.
1581#
1582# Note that getLogger('') now does the same thing, so this function is
1583# deprecated and may disappear in the future.
1584# """
1585# return root
1586
1587def critical(msg, *args, **kwargs):
1588 """
1589 Log a message with severity 'CRITICAL' on the root logger.
1590 """
1591 if len(root.handlers) == 0:
1592 basicConfig()
1593 root.critical(msg, *args, **kwargs)
1594
1595fatal = critical
1596
1597def error(msg, *args, **kwargs):
1598 """
1599 Log a message with severity 'ERROR' on the root logger.
1600 """
1601 if len(root.handlers) == 0:
1602 basicConfig()
1603 root.error(msg, *args, **kwargs)
1604
1605def exception(msg, *args, **kwargs):
1606 """
1607 Log a message with severity 'ERROR' on the root logger,
1608 with exception information.
1609 """
1610 kwargs['exc_info'] = 1
1611 error(msg, *args, **kwargs)
1612
1613def warning(msg, *args, **kwargs):
1614 """
1615 Log a message with severity 'WARNING' on the root logger.
1616 """
1617 if len(root.handlers) == 0:
1618 basicConfig()
1619 root.warning(msg, *args, **kwargs)
1620
1621warn = warning
1622
1623def info(msg, *args, **kwargs):
1624 """
1625 Log a message with severity 'INFO' on the root logger.
1626 """
1627 if len(root.handlers) == 0:
1628 basicConfig()
1629 root.info(msg, *args, **kwargs)
1630
1631def debug(msg, *args, **kwargs):
1632 """
1633 Log a message with severity 'DEBUG' on the root logger.
1634 """
1635 if len(root.handlers) == 0:
1636 basicConfig()
1637 root.debug(msg, *args, **kwargs)
1638
1639def log(level, msg, *args, **kwargs):
1640 """
1641 Log 'msg % args' with the integer severity 'level' on the root logger.
1642 """
1643 if len(root.handlers) == 0:
1644 basicConfig()
1645 root.log(level, msg, *args, **kwargs)
1646
1647def disable(level):
1648 """
1649 Disable all logging calls of severity 'level' and below.
1650 """
1651 root.manager.disable = level
1652
1653def shutdown(handlerList=_handlerList):
1654 """
1655 Perform any cleanup actions in the logging system (e.g. flushing
1656 buffers).
1657
1658 Should be called at application exit.
1659 """
1660 for wr in reversed(handlerList[:]):
1661 #errors might occur, for example, if files are locked
1662 #we just ignore them if raiseExceptions is not set
1663 try:
1664 h = wr()
1665 if h:
1666 try:
1667 h.acquire()
1668 h.flush()
1669 h.close()
1670 except (IOError, ValueError):
1671 # Ignore errors which might be caused
1672 # because handlers have been closed but
1673 # references to them are still around at
1674 # application exit.
1675 pass
1676 finally:
1677 h.release()
1678 except:
1679 if raiseExceptions:
1680 raise
1681 #else, swallow
1682
1683#Let's try and shutdown automatically on application exit...
1684import atexit
1685atexit.register(shutdown)
1686
1687# Null handler
1688
1689class NullHandler(Handler):
1690 """
1691 This handler does nothing. It's intended to be used to avoid the
1692 "No handlers could be found for logger XXX" one-off warning. This is
1693 important for library code, which may contain code to log events. If a user
1694 of the library does not configure logging, the one-off warning might be
1695 produced; to avoid this, the library developer simply needs to instantiate
1696 a NullHandler and add it to the top-level logger of the library module or
1697 package.
1698 """
1699 def handle(self, record):
1700 pass
1701
1702 def emit(self, record):
1703 pass
1704
1705 def createLock(self):
1706 self.lock = None
1707
1708# Warnings integration
1709
1710_warnings_showwarning = None
1711
1712def _showwarning(message, category, filename, lineno, file=None, line=None):
1713 """
1714 Implementation of showwarnings which redirects to logging, which will first
1715 check to see if the file parameter is None. If a file is specified, it will
1716 delegate to the original warnings implementation of showwarning. Otherwise,
1717 it will call warnings.formatwarning and will log the resulting string to a
1718 warnings logger named "py.warnings" with level logging.WARNING.
1719 """
1720 if file is not None:
1721 if _warnings_showwarning is not None:
1722 _warnings_showwarning(message, category, filename, lineno, file, line)
1723 else:
1724 s = warnings.formatwarning(message, category, filename, lineno, line)
1725 logger = getLogger("py.warnings")
1726 if not logger.handlers:
1727 logger.addHandler(NullHandler())
1728 logger.warning("%s", s)
1729
1730def captureWarnings(capture):
1731 """
1732 If capture is true, redirect all warnings to the logging package.
1733 If capture is False, ensure that warnings are not redirected to logging
1734 but to their original destinations.
1735 """
1736 global _warnings_showwarning
1737 if capture:
1738 if _warnings_showwarning is None:
1739 _warnings_showwarning = warnings.showwarning
1740 warnings.showwarning = _showwarning
1741 else:
1742 if _warnings_showwarning is not None:
1743 warnings.showwarning = _warnings_showwarning
1744 _warnings_showwarning = None