[Python-checkins] cpython (3.2): logging: don't define QueueListener if Python has no thread support

victor.stinner python-checkins at python.org
Mon May 2 16:14:37 CEST 2011


http://hg.python.org/cpython/rev/728e573d7816
changeset:   69781:728e573d7816
branch:      3.2
parent:      69777:89b9b7094068
user:        Victor Stinner <victor.stinner at haypocalc.com>
date:        Mon May 02 16:11:28 2011 +0200
summary:
  logging: don't define QueueListener if Python has no thread support

files:
  Lib/logging/handlers.py  |  184 +++++++++++++-------------
  Lib/test/test_logging.py |    2 +
  Misc/NEWS                |    2 +
  3 files changed, 98 insertions(+), 90 deletions(-)


diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py
--- a/Lib/logging/handlers.py
+++ b/Lib/logging/handlers.py
@@ -27,7 +27,10 @@
 import logging, socket, os, pickle, struct, time, re
 from stat import ST_DEV, ST_INO, ST_MTIME
 import queue
-import threading
+try:
+    import threading
+except ImportError:
+    threading = None
 
 try:
     import codecs
@@ -1218,106 +1221,107 @@
         except:
             self.handleError(record)
 
-class QueueListener(object):
-    """
-    This class implements an internal threaded listener which watches for
-    LogRecords being added to a queue, removes them and passes them to a
-    list of handlers for processing.
-    """
-    _sentinel = None
+if threading:
+    class QueueListener(object):
+        """
+        This class implements an internal threaded listener which watches for
+        LogRecords being added to a queue, removes them and passes them to a
+        list of handlers for processing.
+        """
+        _sentinel = None
 
-    def __init__(self, queue, *handlers):
-        """
-        Initialise an instance with the specified queue and
-        handlers.
-        """
-        self.queue = queue
-        self.handlers = handlers
-        self._stop = threading.Event()
-        self._thread = None
+        def __init__(self, queue, *handlers):
+            """
+            Initialise an instance with the specified queue and
+            handlers.
+            """
+            self.queue = queue
+            self.handlers = handlers
+            self._stop = threading.Event()
+            self._thread = None
 
-    def dequeue(self, block):
-        """
-        Dequeue a record and return it, optionally blocking.
+        def dequeue(self, block):
+            """
+            Dequeue a record and return it, optionally blocking.
 
-        The base implementation uses get. You may want to override this method
-        if you want to use timeouts or work with custom queue implementations.
-        """
-        return self.queue.get(block)
+            The base implementation uses get. You may want to override this method
+            if you want to use timeouts or work with custom queue implementations.
+            """
+            return self.queue.get(block)
 
-    def start(self):
-        """
-        Start the listener.
+        def start(self):
+            """
+            Start the listener.
 
-        This starts up a background thread to monitor the queue for
-        LogRecords to process.
-        """
-        self._thread = t = threading.Thread(target=self._monitor)
-        t.setDaemon(True)
-        t.start()
+            This starts up a background thread to monitor the queue for
+            LogRecords to process.
+            """
+            self._thread = t = threading.Thread(target=self._monitor)
+            t.setDaemon(True)
+            t.start()
 
-    def prepare(self , record):
-        """
-        Prepare a record for handling.
+        def prepare(self , record):
+            """
+            Prepare a record for handling.
 
-        This method just returns the passed-in record. You may want to
-        override this method if you need to do any custom marshalling or
-        manipulation of the record before passing it to the handlers.
-        """
-        return record
+            This method just returns the passed-in record. You may want to
+            override this method if you need to do any custom marshalling or
+            manipulation of the record before passing it to the handlers.
+            """
+            return record
 
-    def handle(self, record):
-        """
-        Handle a record.
+        def handle(self, record):
+            """
+            Handle a record.
 
-        This just loops through the handlers offering them the record
-        to handle.
-        """
-        record = self.prepare(record)
-        for handler in self.handlers:
-            handler.handle(record)
+            This just loops through the handlers offering them the record
+            to handle.
+            """
+            record = self.prepare(record)
+            for handler in self.handlers:
+                handler.handle(record)
 
-    def _monitor(self):
-        """
-        Monitor the queue for records, and ask the handler
-        to deal with them.
+        def _monitor(self):
+            """
+            Monitor the queue for records, and ask the handler
+            to deal with them.
 
-        This method runs on a separate, internal thread.
-        The thread will terminate if it sees a sentinel object in the queue.
-        """
-        q = self.queue
-        has_task_done = hasattr(q, 'task_done')
-        while not self._stop.isSet():
-            try:
-                record = self.dequeue(True)
-                if record is self._sentinel:
+            This method runs on a separate, internal thread.
+            The thread will terminate if it sees a sentinel object in the queue.
+            """
+            q = self.queue
+            has_task_done = hasattr(q, 'task_done')
+            while not self._stop.isSet():
+                try:
+                    record = self.dequeue(True)
+                    if record is self._sentinel:
+                        break
+                    self.handle(record)
+                    if has_task_done:
+                        q.task_done()
+                except queue.Empty:
+                    pass
+            # There might still be records in the queue.
+            while True:
+                try:
+                    record = self.dequeue(False)
+                    if record is self._sentinel:
+                        break
+                    self.handle(record)
+                    if has_task_done:
+                        q.task_done()
+                except queue.Empty:
                     break
-                self.handle(record)
-                if has_task_done:
-                    q.task_done()
-            except queue.Empty:
-                pass
-        # There might still be records in the queue.
-        while True:
-            try:
-                record = self.dequeue(False)
-                if record is self._sentinel:
-                    break
-                self.handle(record)
-                if has_task_done:
-                    q.task_done()
-            except queue.Empty:
-                break
 
-    def stop(self):
-        """
-        Stop the listener.
+        def stop(self):
+            """
+            Stop the listener.
 
-        This asks the thread to terminate, and then waits for it to do so.
-        Note that if you don't call this before your application exits, there
-        may be some records still left on the queue, which won't be processed.
-        """
-        self._stop.set()
-        self.queue.put_nowait(self._sentinel)
-        self._thread.join()
-        self._thread = None
+            This asks the thread to terminate, and then waits for it to do so.
+            Note that if you don't call this before your application exits, there
+            may be some records still left on the queue, which won't be processed.
+            """
+            self._stop.set()
+            self.queue.put_nowait(self._sentinel)
+            self._thread.join()
+            self._thread = None
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -2093,6 +2093,8 @@
         self.assertEqual(data.name, self.que_logger.name)
         self.assertEqual((data.msg, data.args), (msg, None))
 
+    @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
+                         'logging.handlers.QueueListener required for this test')
     def test_queue_listener(self):
         handler = TestHandler(Matcher())
         listener = logging.handlers.QueueListener(self.queue, handler)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -79,6 +79,8 @@
 Library
 -------
 
+- logging: don't define QueueListener if Python has no thread support.
+
 - Issue #11277: mmap.mmap() calls fcntl(fd, F_FULLFSYNC) on Mac OS X to get
   around a mmap bug with sparse files. Patch written by Steffen Daode Nurpmeso.
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list