https://github.com/python/cpython/commit/1dcdac6e084471c14b4690ae9154b928e93a7222
commit: 1dcdac6e084471c14b4690ae9154b928e93a7222
branch: 3.13
author: Vinay Sajip <[email protected]>
committer: vsajip <[email protected]>
date: 2025-04-13T13:00:50+01:00
summary:
[3.13] gh-132106: Ensure that running `logging.handlers.QueueListener…
(GH-132471)
Cherry-picked using 5863cd70b8782313b52bb8c71a4127d7ea4c50e9
files:
A Misc/NEWS.d/next/Library/2025-04-12-09-30-24.gh-issue-132106.OxUds3.rst
M Doc/library/logging.handlers.rst
M Lib/logging/handlers.py
M Lib/test/test_logging.py
diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst
index 5a081f9e7add99..e63c253e123552 100644
--- a/Doc/library/logging.handlers.rst
+++ b/Doc/library/logging.handlers.rst
@@ -1172,6 +1172,10 @@ possible, while any potentially slow operations (such as
sending an email via
This starts up a background thread to monitor the queue for
LogRecords to process.
+ .. versionchanged:: next
+ Raises :exc:`RuntimeError` if called and the listener is already
+ running.
+
.. method:: stop()
Stops the listener.
diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py
index da9c59c119f3db..d3ea06c731ef89 100644
--- a/Lib/logging/handlers.py
+++ b/Lib/logging/handlers.py
@@ -1545,6 +1545,9 @@ def start(self):
This starts up a background thread to monitor the queue for
LogRecords to process.
"""
+ if self._thread is not None:
+ raise RuntimeError("Listener already started")
+
self._thread = t = threading.Thread(target=self._monitor)
t.daemon = True
t.start()
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index 678c23dad67faa..58e0381c4aa934 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -4300,8 +4300,6 @@ def test_formatting(self):
self.assertEqual(formatted_msg, log_record.msg)
self.assertEqual(formatted_msg, log_record.message)
- @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
- 'logging.handlers.QueueListener required for this
test')
def test_queue_listener(self):
handler = TestHandler(support.Matcher())
listener = logging.handlers.QueueListener(self.queue, handler)
@@ -4336,8 +4334,18 @@ def test_queue_listener(self):
self.assertTrue(handler.matches(levelno=logging.CRITICAL, message='6'))
handler.close()
- @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
- 'logging.handlers.QueueListener required for this
test')
+ # doesn't hurt to call stop() more than once.
+ listener.stop()
+ self.assertIsNone(listener._thread)
+
+ def test_queue_listener_multi_start(self):
+ handler = TestHandler(support.Matcher())
+ listener = logging.handlers.QueueListener(self.queue, handler)
+ listener.start()
+ self.assertRaises(RuntimeError, listener.start)
+ listener.stop()
+ self.assertIsNone(listener._thread)
+
def test_queue_listener_with_StreamHandler(self):
# Test that traceback and stack-info only appends once (bpo-34334,
bpo-46755).
listener = logging.handlers.QueueListener(self.queue, self.root_hdlr)
@@ -4352,8 +4360,6 @@ def test_queue_listener_with_StreamHandler(self):
self.assertEqual(self.stream.getvalue().strip().count('Traceback'), 1)
self.assertEqual(self.stream.getvalue().strip().count('Stack'), 1)
- @unittest.skipUnless(hasattr(logging.handlers, 'QueueListener'),
- 'logging.handlers.QueueListener required for this
test')
def test_queue_listener_with_multiple_handlers(self):
# Test that queue handler format doesn't affect other handler formats
(bpo-35726).
self.que_hdlr.setFormatter(self.root_formatter)
diff --git
a/Misc/NEWS.d/next/Library/2025-04-12-09-30-24.gh-issue-132106.OxUds3.rst
b/Misc/NEWS.d/next/Library/2025-04-12-09-30-24.gh-issue-132106.OxUds3.rst
new file mode 100644
index 00000000000000..b6d58a29f9b42f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-04-12-09-30-24.gh-issue-132106.OxUds3.rst
@@ -0,0 +1,2 @@
+:meth:`QueueListener.start <logging.handlers.QueueListener.start>` now
+raises a :exc:`RuntimeError` if the listener is already started.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]