summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@haypocalc.com>2011-05-02 14:11:28 (GMT)
committerVictor Stinner <victor.stinner@haypocalc.com>2011-05-02 14:11:28 (GMT)
commitcafa2efedbaa4e0d4023e1cde48fc8f58d1a44cb (patch)
treecc6f9c4fe0df3fc7cd97ab4e3bb0772ac9fcc725
parentb912c5a004068e472b1b46fad68445e70934e280 (diff)
downloadcpython-cafa2efedbaa4e0d4023e1cde48fc8f58d1a44cb.zip
cpython-cafa2efedbaa4e0d4023e1cde48fc8f58d1a44cb.tar.gz
cpython-cafa2efedbaa4e0d4023e1cde48fc8f58d1a44cb.tar.bz2
logging: don't define QueueListener if Python has no thread support
-rw-r--r--Lib/logging/handlers.py208
-rw-r--r--Lib/test/test_logging.py2
-rw-r--r--Misc/NEWS2
3 files changed, 110 insertions, 102 deletions
diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py
index 3a48628..306cf86 100644
--- a/Lib/logging/handlers.py
+++ b/Lib/logging/handlers.py
@@ -27,7 +27,10 @@ To use, simply 'import logging.handlers' and log away!
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 @@ class QueueHandler(logging.Handler):
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
-
- 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.
-
- 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.
-
- 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.
-
- 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.
-
- 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.
-
- 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:
+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 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)
+
+ 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()
+
+ 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
+
+ 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)
+
+ 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:
+ 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:
- break
-
- 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
+ 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
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index 6623a0f..90d293e 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -2093,6 +2093,8 @@ class QueueHandlerTest(BaseTest):
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
index 2a50094..8ca2f02 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -79,6 +79,8 @@ Core and Builtins
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.