diff options
author | Victor Stinner <victor.stinner@haypocalc.com> | 2011-05-02 14:11:28 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@haypocalc.com> | 2011-05-02 14:11:28 (GMT) |
commit | cafa2efedbaa4e0d4023e1cde48fc8f58d1a44cb (patch) | |
tree | cc6f9c4fe0df3fc7cd97ab4e3bb0772ac9fcc725 | |
parent | b912c5a004068e472b1b46fad68445e70934e280 (diff) | |
download | cpython-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.py | 208 | ||||
-rw-r--r-- | Lib/test/test_logging.py | 2 | ||||
-rw-r--r-- | Misc/NEWS | 2 |
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) @@ -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. |