From af834ad6b971e8dc61bb34217b7c738e922a79e6 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 23 Jul 2026 17:14:12 +0300 Subject: [PATCH] gh-135683: Honor raiseExceptions when opening the file fails in FileHandler FileHandler and WatchedFileHandler opened the file outside the try block that reports errors via handleError(), so an error while opening the file was raised instead of being handled, ignoring raiseExceptions. Co-Authored-By: Claude Opus 4.8 (1M context) --- Lib/logging/__init__.py | 7 +++- Lib/logging/handlers.py | 9 ++++-- Lib/test/test_logging.py | 32 +++++++++++++++++++ ...-07-23-14-13-39.gh-issue-135683.droBu7.rst | 3 ++ 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-07-23-14-13-39.gh-issue-135683.droBu7.rst diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index b4a5f5cc2f598f5..05715b777fa80c0 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -1263,7 +1263,12 @@ def emit(self, record): """ if self.stream is None: if self.mode != 'w' or not self._closed: - self.stream = self._open() + # Report an error while opening the file, like emit errors. + try: + self.stream = self._open() + except Exception: + self.handleError(record) + return if self.stream: StreamHandler.emit(self, record) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index a5394d2dbea6494..a4816f56c7f9230 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -563,8 +563,13 @@ def emit(self, record): If underlying file has changed, reopen the file before emitting the record to it. """ - self.reopenIfNeeded() - logging.FileHandler.emit(self, record) + # Report an error while reopening the file, like emit errors. + try: + self.reopenIfNeeded() + except Exception: + self.handleError(record) + else: + logging.FileHandler.emit(self, record) class SocketHandler(logging.Handler): diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 06b3aa66fc47a31..b21163eb1ef1eff 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -6416,6 +6416,38 @@ def test_emit_after_closing_in_write_mode(self): with open(self.fn) as fp: self.assertEqual(fp.read().strip(), '1') + def test_emit_open_error(self): + # gh-135683: an error while opening the file in emit() respects + # raiseExceptions, like an error during the actual write. + d = tempfile.mkdtemp() + self.addCleanup(os_helper.rmtree, d) + r = logging.makeLogRecord({}) + old_raise = logging.raiseExceptions + self.addCleanup(setattr, logging, 'raiseExceptions', old_raise) + + # FileHandler with delay: the failing open happens in emit(). + fh = logging.FileHandler(os.path.join(d, 'missing', 'a.log'), + encoding='utf-8', delay=True) + self.addCleanup(fh.close) + # WatchedFileHandler: reopenIfNeeded() fails after the dir is removed. + subdir = os.path.join(d, 'sub') + os.mkdir(subdir) + wfh = logging.handlers.WatchedFileHandler( + os.path.join(subdir, 'b.log'), encoding='utf-8') + self.addCleanup(wfh.close) + os_helper.rmtree(subdir) + + for h in (fh, wfh): + logging.raiseExceptions = True + with support.captured_stderr() as stderr: + h.handle(r) + self.assertIn('\nFileNotFoundError:', stderr.getvalue()) + + logging.raiseExceptions = False + with support.captured_stderr() as stderr: + h.handle(r) + self.assertEqual('', stderr.getvalue()) + class RotatingFileHandlerTest(BaseFileTest): def test_should_not_rollover(self): # If file is empty rollover never occurs diff --git a/Misc/NEWS.d/next/Library/2026-07-23-14-13-39.gh-issue-135683.droBu7.rst b/Misc/NEWS.d/next/Library/2026-07-23-14-13-39.gh-issue-135683.droBu7.rst new file mode 100644 index 000000000000000..532ae22d017a565 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-23-14-13-39.gh-issue-135683.droBu7.rst @@ -0,0 +1,3 @@ +:class:`logging.FileHandler` and :class:`logging.handlers.WatchedFileHandler` +now honor :data:`logging.raiseExceptions` for errors that occur while opening +the file, like for other errors during logging.