diff --git a/Tests/test_image.py b/Tests/test_image.py index 9efd4c4677d..f0861bb4f81 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -1,4 +1,5 @@ import io +import logging import os import shutil import sys @@ -1014,6 +1015,15 @@ def test_fli_overrun2(self): except OSError as e: assert str(e) == "buffer overrun when reading image file" + def test_close_graceful(self, caplog): + with Image.open("Tests/images/hopper.jpg") as im: + copy = im.copy() + with caplog.at_level(logging.DEBUG): + im.close() + copy.close() + assert len(caplog.records) == 0 + assert im.fp is None + class MockEncoder: pass diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 546d9020334..d435b561720 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -549,16 +549,17 @@ def close(self): :py:meth:`~PIL.Image.Image.load` method. See :ref:`file-handling` for more information. """ - try: - if getattr(self, "_fp", False): - if self._fp != self.fp: - self._fp.close() - self._fp = DeferredError(ValueError("Operation on closed image")) - if self.fp: - self.fp.close() - self.fp = None - except Exception as msg: - logger.debug("Error closing: %s", msg) + if hasattr(self, "fp"): + try: + if getattr(self, "_fp", False): + if self._fp != self.fp: + self._fp.close() + self._fp = DeferredError(ValueError("Operation on closed image")) + if self.fp: + self.fp.close() + self.fp = None + except Exception as msg: + logger.debug("Error closing: %s", msg) if getattr(self, "map", None): self.map = None