mirror of https://github.com/python/cpython
logging: don't define QueueListener if Python has no thread support
This commit is contained in:
parent
b912c5a004
commit
cafa2efedb
|
@ -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
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue