diff --git a/docs/reference/open_files.rst b/docs/reference/open_files.rst index a31a1f37e..511eb97bf 100644 --- a/docs/reference/open_files.rst +++ b/docs/reference/open_files.rst @@ -4,7 +4,7 @@ File Handling in Pillow ======================= When opening a file as an image, Pillow requires a filename, -pathlib.Path object, or a file-like object. Pillow uses the filename +pathlib.Path object, or a file-like object. Pillow uses the filename or Path to open a file, so for the rest of this article, they will all be treated as a file-like object. @@ -30,10 +30,10 @@ and may fail:: im5 = Image.open(f) im5.load() # FAILS, closed file -The documentation specifies that the file will be closed after the -``Image.Image.load()`` method is called. This is an aspirational -specification rather than an accurate reflection of the state of the -code. +If a filename or a path-like object is passed to Pillow, then the resulting +file object opened by Pillow may also be closed by Pillow after the +``Image.Image.load()`` method is called, provided the associated image does not +have multiple frames. Pillow cannot in general close and reopen a file, so any access to that file needs to be prior to the close. @@ -41,12 +41,6 @@ that file needs to be prior to the close. Issues ------ -The current open file handling is inconsistent at best: - -* Most of the image plugins do not close the input file. -* Multi-frame images behave badly when seeking through the file, as - it's legal to seek backward in the file until the last image is - read, and then it's not. * Using the file context manager to provide a file-like object to Pillow is dangerous unless the context of the image is limited to the context of the file. @@ -54,20 +48,20 @@ The current open file handling is inconsistent at best: Image Lifecycle --------------- -* ``Image.open()`` called. Path-like objects are opened as a - file. Metadata is read from the open file. The file is left open for - further usage. +* ``Image.open()`` Path-like objects are opened as a file. Metadata is read + from the open file. The file is left open for further usage. -* ``Image.Image.load()`` when the pixel data from the image is +* ``Image.Image.load()`` When the pixel data from the image is required, ``load()`` is called. The current frame is read into memory. The image can now be used independently of the underlying image file. -* ``Image.Image.seek()`` in the case of multi-frame images - (e.g. multipage TIFF and animated GIF) the image file left open so - that seek can load the appropriate frame. When the last frame is - read, the image file is closed (at least in some image plugins), and - no more seeks can occur. + If a filename or a path-like object was passed to ``Image.open()``, then + the file object was opened by Pillow and is considered to be used exclusively + by Pillow. So if the image is a single-frame image, the file will + be closed in this method after the frame is read. If the image is a + multi-frame image, (e.g. multipage TIFF and animated GIF) the image file is + left open so that ``Image.Image.seek()`` can load the appropriate frame. * ``Image.Image.close()`` Closes the file pointer and destroys the core image object. This is used in the Pillow context manager @@ -77,16 +71,13 @@ Image Lifecycle ... # image operations here. -The lifecycle of a single frame image is relatively simple. The file +The lifecycle of a single-frame image is relatively simple. The file must remain open until the ``load()`` or ``close()`` function is called. Multi-frame images are more complicated. The ``load()`` method is not -a terminal method, so it should not close the underlying file. The -current behavior of ``seek()`` closing the underlying file on -accessing the last frame is presumably a heuristic for closing the -file after iterating through the entire sequence. In general, Pillow -does not know if there are going to be any requests for additional +a terminal method, so it should not close the underlying file. In general, +Pillow does not know if there are going to be any requests for additional data until the caller has explicitly closed the image. @@ -124,4 +115,3 @@ Proposed File Handling * Users of the library should call ``Image.Image.close()`` on any multi-frame image to ensure that the underlying file is closed. - diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 2f6b35c07..e8d003154 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -827,8 +827,10 @@ class Image(object): Image class automatically loads an opened image when it is accessed for the first time. - This method will close the file associated with the image. See - :ref:`file-handling` for more information. + If the file associated with the image was opened by Pillow, then this + method will close it. The exception to this is if the image has + multiple frames, in which case the file will be left open for seek + operations. See :ref:`file-handling` for more information. :returns: An image access object. :rtype: :ref:`PixelAccess` or :py:class:`PIL.PyAccess`