diff options
author | Benjamin Peterson <benjamin@python.org> | 2009-11-25 17:19:56 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2009-11-25 17:19:56 (GMT) |
commit | 5554993d375b43114ac6b431d596a0ef2cb58a5e (patch) | |
tree | 0d42a6f5293a52029bdf481a68d253c803abf132 /Lib/logging/__init__.py | |
parent | 88e64a0197eceec99a97da213e42bb90d0a3fd81 (diff) | |
download | cpython-5554993d375b43114ac6b431d596a0ef2cb58a5e.zip cpython-5554993d375b43114ac6b431d596a0ef2cb58a5e.tar.gz cpython-5554993d375b43114ac6b431d596a0ef2cb58a5e.tar.bz2 |
Merged revisions 76498,76507-76509 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r76498 | vinay.sajip | 2009-11-24 09:53:25 -0600 (Tue, 24 Nov 2009) | 1 line
Made logging classes new-style and added name property to handlers.
........
r76507 | vinay.sajip | 2009-11-25 03:03:30 -0600 (Wed, 25 Nov 2009) | 1 line
Issue #6615: logging: Used weak references in internal handler list. Thanks to flox (Florent Xicluna) for the patch.
........
r76508 | vinay.sajip | 2009-11-25 03:22:47 -0600 (Wed, 25 Nov 2009) | 1 line
logging: made _handlers a WeakValueDictionary.
........
r76509 | vinay.sajip | 2009-11-25 08:12:03 -0600 (Wed, 25 Nov 2009) | 1 line
logging: Issue 6615: Changed handler prepend to append.
........
Diffstat (limited to 'Lib/logging/__init__.py')
-rw-r--r-- | Lib/logging/__init__.py | 84 |
1 files changed, 59 insertions, 25 deletions
diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index e64d86b..6ff2216 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -23,7 +23,7 @@ Copyright (C) 2001-2009 Vinay Sajip. All Rights Reserved. To use, simply 'import logging' and log away! """ -import sys, os, time, io, traceback, warnings +import sys, os, time, io, traceback, warnings, weakref __all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR', 'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO', @@ -46,8 +46,8 @@ except ImportError: __author__ = "Vinay Sajip <vinay_sajip@red-dove.com>" __status__ = "production" -__version__ = "0.5.0.9" -__date__ = "09 October 2009" +__version__ = "0.5.1.1" +__date__ = "25 November 2009" #--------------------------------------------------------------------------- # Miscellaneous module data @@ -193,9 +193,9 @@ def _checkLevel(level): # #_lock is used to serialize access to shared data structures in this module. -#This needs to be an RLock because fileConfig() creates Handlers and so -#might arbitrary user threads. Since Handler.__init__() updates the shared -#dictionary _handlers, it needs to acquire the lock. But if configuring, +#This needs to be an RLock because fileConfig() creates and configures +#Handlers, and so might arbitrary user threads. Since Handler code updates the +#shared dictionary _handlers, it needs to acquire the lock. But if configuring, #the lock would already have been acquired - so we need an RLock. #The same argument applies to Loggers and Manager.loggerDict. # @@ -224,7 +224,7 @@ def _releaseLock(): # The logging record #--------------------------------------------------------------------------- -class LogRecord: +class LogRecord(object): """ A LogRecord instance represents an event being logged. @@ -332,7 +332,7 @@ def makeLogRecord(dict): # Formatter classes and functions #--------------------------------------------------------------------------- -class Formatter: +class Formatter(object): """ Formatter instances are used to convert a LogRecord to text. @@ -464,7 +464,7 @@ class Formatter: # _defaultFormatter = Formatter() -class BufferingFormatter: +class BufferingFormatter(object): """ A formatter suitable for formatting a number of records. """ @@ -506,7 +506,7 @@ class BufferingFormatter: # Filter classes and functions #--------------------------------------------------------------------------- -class Filter: +class Filter(object): """ Filter instances are used to perform arbitrary filtering of LogRecords. @@ -543,7 +543,7 @@ class Filter: return 0 return (record.name[self.nlen] == ".") -class Filterer: +class Filterer(object): """ A base class for loggers and handlers which allows them to share common code. @@ -587,9 +587,30 @@ class Filterer: # Handler classes and functions #--------------------------------------------------------------------------- -_handlers = {} #repository of handlers (for flushing when shutdown called) +_handlers = weakref.WeakValueDictionary() #map of handler names to handlers _handlerList = [] # added to allow handlers to be removed in reverse of order initialized +def _removeHandlerRef(wr): + """ + Remove a handler reference from the internal cleanup list. + """ + _acquireLock() + try: + if wr in _handlerList: + _handlerList.remove(wr) + finally: + _releaseLock() + +def _addHandlerRef(handler): + """ + Add a handler to the internal cleanup list using a weak reference. + """ + _acquireLock() + try: + _handlerList.append(weakref.ref(handler, _removeHandlerRef)) + finally: + _releaseLock() + class Handler(Filterer): """ Handler instances dispatch logging events to specific destinations. @@ -605,16 +626,28 @@ class Handler(Filterer): and the filter list to empty. """ Filterer.__init__(self) + self._name = None self.level = _checkLevel(level) self.formatter = None - #get the module data lock, as we're updating a shared structure. + # Add the handler to the global _handlerList (for cleanup on shutdown) + _addHandlerRef(self) + self.createLock() + + def get_name(self): + return self._name + + def set_name(self, name): _acquireLock() - try: #unlikely to raise an exception, but you never know... - _handlers[self] = 1 - _handlerList.insert(0, self) + try: + if self._name in _handlers: + del _handlers[self._name] + self._name = name + if name: + _handlers[name] = self finally: _releaseLock() - self.createLock() + + name = property(get_name, set_name) def createLock(self): """ @@ -705,16 +738,16 @@ class Handler(Filterer): """ Tidy up any resources used by the handler. - This version does removes the handler from an internal list - of handlers which is closed when shutdown() is called. Subclasses + This version removes the handler from an internal map of handlers, + _handlers, which is used for handler lookup by name. Subclasses should ensure that this gets called from overridden close() methods. """ #get the module data lock, as we're updating a shared structure. _acquireLock() try: #unlikely to raise an exception, but you never know... - del _handlers[self] - _handlerList.remove(self) + if self._name and self._name in _handlers: + del _handlers[self._name] finally: _releaseLock() @@ -866,7 +899,7 @@ class FileHandler(StreamHandler): # Manager classes and functions #--------------------------------------------------------------------------- -class PlaceHolder: +class PlaceHolder(object): """ PlaceHolder instances are used in the Manager logger hierarchy to take the place of nodes for which no loggers have been defined. This class is @@ -913,7 +946,7 @@ def getLoggerClass(): return _loggerClass -class Manager: +class Manager(object): """ There is [under normal circumstances] just one Manager instance, which holds the hierarchy of loggers. @@ -1266,7 +1299,7 @@ class RootLogger(Logger): _loggerClass = Logger -class LoggerAdapter: +class LoggerAdapter(object): """ An adapter for loggers which makes it easier to specify contextual information in logging output. @@ -1512,10 +1545,11 @@ def shutdown(handlerList=_handlerList): Should be called at application exit. """ - for h in handlerList[:]: + for wr in reversed(handlerList[:]): #errors might occur, for example, if files are locked #we just ignore them if raiseExceptions is not set try: + h = wr() h.flush() h.close() except: |