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.