PyXR

c:\python24\lib \ logging \ config.py



0001 # Copyright 2001-2004 by Vinay Sajip. All Rights Reserved.
0002 #
0003 # Permission to use, copy, modify, and distribute this software and its
0004 # documentation for any purpose and without fee is hereby granted,
0005 # provided that the above copyright notice appear in all copies and that
0006 # both that copyright notice and this permission notice appear in
0007 # supporting documentation, and that the name of Vinay Sajip
0008 # not be used in advertising or publicity pertaining to distribution
0009 # of the software without specific, written prior permission.
0010 # VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
0011 # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
0012 # VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
0013 # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
0014 # IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
0015 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0016 
0017 """
0018 Configuration functions for the logging package for Python. The core package
0019 is based on PEP 282 and comments thereto in comp.lang.python, and influenced
0020 by Apache's log4j system.
0021 
0022 Should work under Python versions >= 1.5.2, except that source line
0023 information is not available unless 'sys._getframe()' is.
0024 
0025 Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
0026 
0027 To use, simply 'import logging' and log away!
0028 """
0029 
0030 import sys, logging, logging.handlers, string, thread, threading, socket, struct, os
0031 
0032 from SocketServer import ThreadingTCPServer, StreamRequestHandler
0033 
0034 
0035 DEFAULT_LOGGING_CONFIG_PORT = 9030
0036 
0037 if sys.platform == "win32":
0038     RESET_ERROR = 10054   #WSAECONNRESET
0039 else:
0040     RESET_ERROR = 104     #ECONNRESET
0041 
0042 #
0043 #   The following code implements a socket listener for on-the-fly
0044 #   reconfiguration of logging.
0045 #
0046 #   _listener holds the server object doing the listening
0047 _listener = None
0048 
0049 def fileConfig(fname, defaults=None):
0050     """
0051     Read the logging configuration from a ConfigParser-format file.
0052 
0053     This can be called several times from an application, allowing an end user
0054     the ability to select from various pre-canned configurations (if the
0055     developer provides a mechanism to present the choices and load the chosen
0056     configuration).
0057     In versions of ConfigParser which have the readfp method [typically
0058     shipped in 2.x versions of Python], you can pass in a file-like object
0059     rather than a filename, in which case the file-like object will be read
0060     using readfp.
0061     """
0062     import ConfigParser
0063 
0064     cp = ConfigParser.ConfigParser(defaults)
0065     if hasattr(cp, 'readfp') and hasattr(fname, 'readline'):
0066         cp.readfp(fname)
0067     else:
0068         cp.read(fname)
0069     #first, do the formatters...
0070     flist = cp.get("formatters", "keys")
0071     if len(flist):
0072         flist = string.split(flist, ",")
0073         formatters = {}
0074         for form in flist:
0075             sectname = "formatter_%s" % form
0076             opts = cp.options(sectname)
0077             if "format" in opts:
0078                 fs = cp.get(sectname, "format", 1)
0079             else:
0080                 fs = None
0081             if "datefmt" in opts:
0082                 dfs = cp.get(sectname, "datefmt", 1)
0083             else:
0084                 dfs = None
0085             f = logging.Formatter(fs, dfs)
0086             formatters[form] = f
0087     #next, do the handlers...
0088     #critical section...
0089     logging._acquireLock()
0090     try:
0091         try:
0092             #first, lose the existing handlers...
0093             logging._handlers.clear()
0094             #now set up the new ones...
0095             hlist = cp.get("handlers", "keys")
0096             if len(hlist):
0097                 hlist = string.split(hlist, ",")
0098                 handlers = {}
0099                 fixups = [] #for inter-handler references
0100                 for hand in hlist:
0101                     try:
0102                         sectname = "handler_%s" % hand
0103                         klass = cp.get(sectname, "class")
0104                         opts = cp.options(sectname)
0105                         if "formatter" in opts:
0106                             fmt = cp.get(sectname, "formatter")
0107                         else:
0108                             fmt = ""
0109                         klass = eval(klass, vars(logging))
0110                         args = cp.get(sectname, "args")
0111                         args = eval(args, vars(logging))
0112                         h = apply(klass, args)
0113                         if "level" in opts:
0114                             level = cp.get(sectname, "level")
0115                             h.setLevel(logging._levelNames[level])
0116                         if len(fmt):
0117                             h.setFormatter(formatters[fmt])
0118                         #temporary hack for FileHandler and MemoryHandler.
0119                         if klass == logging.handlers.MemoryHandler:
0120                             if "target" in opts:
0121                                 target = cp.get(sectname,"target")
0122                             else:
0123                                 target = ""
0124                             if len(target): #the target handler may not be loaded yet, so keep for later...
0125                                 fixups.append((h, target))
0126                         handlers[hand] = h
0127                     except:     #if an error occurs when instantiating a handler, too bad
0128                         pass    #this could happen e.g. because of lack of privileges
0129                 #now all handlers are loaded, fixup inter-handler references...
0130                 for fixup in fixups:
0131                     h = fixup[0]
0132                     t = fixup[1]
0133                     h.setTarget(handlers[t])
0134             #at last, the loggers...first the root...
0135             llist = cp.get("loggers", "keys")
0136             llist = string.split(llist, ",")
0137             llist.remove("root")
0138             sectname = "logger_root"
0139             root = logging.root
0140             log = root
0141             opts = cp.options(sectname)
0142             if "level" in opts:
0143                 level = cp.get(sectname, "level")
0144                 log.setLevel(logging._levelNames[level])
0145             for h in root.handlers[:]:
0146                 root.removeHandler(h)
0147             hlist = cp.get(sectname, "handlers")
0148             if len(hlist):
0149                 hlist = string.split(hlist, ",")
0150                 for hand in hlist:
0151                     log.addHandler(handlers[hand])
0152             #and now the others...
0153             #we don't want to lose the existing loggers,
0154             #since other threads may have pointers to them.
0155             #existing is set to contain all existing loggers,
0156             #and as we go through the new configuration we
0157             #remove any which are configured. At the end,
0158             #what's left in existing is the set of loggers
0159             #which were in the previous configuration but
0160             #which are not in the new configuration.
0161             existing = root.manager.loggerDict.keys()
0162             #now set up the new ones...
0163             for log in llist:
0164                 sectname = "logger_%s" % log
0165                 qn = cp.get(sectname, "qualname")
0166                 opts = cp.options(sectname)
0167                 if "propagate" in opts:
0168                     propagate = cp.getint(sectname, "propagate")
0169                 else:
0170                     propagate = 1
0171                 logger = logging.getLogger(qn)
0172                 if qn in existing:
0173                     existing.remove(qn)
0174                 if "level" in opts:
0175                     level = cp.get(sectname, "level")
0176                     logger.setLevel(logging._levelNames[level])
0177                 for h in logger.handlers[:]:
0178                     logger.removeHandler(h)
0179                 logger.propagate = propagate
0180                 logger.disabled = 0
0181                 hlist = cp.get(sectname, "handlers")
0182                 if len(hlist):
0183                     hlist = string.split(hlist, ",")
0184                     for hand in hlist:
0185                         logger.addHandler(handlers[hand])
0186             #Disable any old loggers. There's no point deleting
0187             #them as other threads may continue to hold references
0188             #and by disabling them, you stop them doing any logging.
0189             for log in existing:
0190                 root.manager.loggerDict[log].disabled = 1
0191         except:
0192             import traceback
0193             ei = sys.exc_info()
0194             traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
0195             del ei
0196     finally:
0197         logging._releaseLock()
0198 
0199 def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
0200     """
0201     Start up a socket server on the specified port, and listen for new
0202     configurations.
0203 
0204     These will be sent as a file suitable for processing by fileConfig().
0205     Returns a Thread object on which you can call start() to start the server,
0206     and which you can join() when appropriate. To stop the server, call
0207     stopListening().
0208     """
0209     if not thread:
0210         raise NotImplementedError, "listen() needs threading to work"
0211 
0212     class ConfigStreamHandler(StreamRequestHandler):
0213         """
0214         Handler for a logging configuration request.
0215 
0216         It expects a completely new logging configuration and uses fileConfig
0217         to install it.
0218         """
0219         def handle(self):
0220             """
0221             Handle a request.
0222 
0223             Each request is expected to be a 4-byte length,
0224             followed by the config file. Uses fileConfig() to do the
0225             grunt work.
0226             """
0227             import tempfile
0228             try:
0229                 conn = self.connection
0230                 chunk = conn.recv(4)
0231                 if len(chunk) == 4:
0232                     slen = struct.unpack(">L", chunk)[0]
0233                     chunk = self.connection.recv(slen)
0234                     while len(chunk) < slen:
0235                         chunk = chunk + conn.recv(slen - len(chunk))
0236                     #Apply new configuration. We'd like to be able to
0237                     #create a StringIO and pass that in, but unfortunately
0238                     #1.5.2 ConfigParser does not support reading file
0239                     #objects, only actual files. So we create a temporary
0240                     #file and remove it later.
0241                     file = tempfile.mktemp(".ini")
0242                     f = open(file, "w")
0243                     f.write(chunk)
0244                     f.close()
0245                     fileConfig(file)
0246                     os.remove(file)
0247             except socket.error, e:
0248                 if type(e.args) != types.TupleType:
0249                     raise
0250                 else:
0251                     errcode = e.args[0]
0252                     if errcode != RESET_ERROR:
0253                         raise
0254 
0255     class ConfigSocketReceiver(ThreadingTCPServer):
0256         """
0257         A simple TCP socket-based logging config receiver.
0258         """
0259 
0260         allow_reuse_address = 1
0261 
0262         def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT,
0263                      handler=None):
0264             ThreadingTCPServer.__init__(self, (host, port), handler)
0265             logging._acquireLock()
0266             self.abort = 0
0267             logging._releaseLock()
0268             self.timeout = 1
0269 
0270         def serve_until_stopped(self):
0271             import select
0272             abort = 0
0273             while not abort:
0274                 rd, wr, ex = select.select([self.socket.fileno()],
0275                                            [], [],
0276                                            self.timeout)
0277                 if rd:
0278                     self.handle_request()
0279                 logging._acquireLock()
0280                 abort = self.abort
0281                 logging._releaseLock()
0282 
0283     def serve(rcvr, hdlr, port):
0284         server = rcvr(port=port, handler=hdlr)
0285         global _listener
0286         logging._acquireLock()
0287         _listener = server
0288         logging._releaseLock()
0289         server.serve_until_stopped()
0290 
0291     return threading.Thread(target=serve,
0292                             args=(ConfigSocketReceiver,
0293                                   ConfigStreamHandler, port))
0294 
0295 def stopListening():
0296     """
0297     Stop the listening server which was created with a call to listen().
0298     """
0299     global _listener
0300     if _listener:
0301         logging._acquireLock()
0302         _listener.abort = 1
0303         _listener = None
0304         logging._releaseLock()
0305 

Generated by PyXR 0.9.4
SourceForge.net Logo