Merge pull request #3490 from radarhere/open_files

Updated open files documentation
This commit is contained in:
Hugo 2018-12-13 21:14:22 +02:00 committed by GitHub
commit 69837baba2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 29 deletions

View File

@ -4,7 +4,7 @@ File Handling in Pillow
======================= =======================
When opening a file as an image, Pillow requires a filename, 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 or Path to open a file, so for the rest of this article, they will all
be treated as a file-like object. be treated as a file-like object.
@ -30,10 +30,10 @@ and may fail::
im5 = Image.open(f) im5 = Image.open(f)
im5.load() # FAILS, closed file im5.load() # FAILS, closed file
The documentation specifies that the file will be closed after the If a filename or a path-like object is passed to Pillow, then the resulting
``Image.Image.load()`` method is called. This is an aspirational file object opened by Pillow may also be closed by Pillow after the
specification rather than an accurate reflection of the state of the ``Image.Image.load()`` method is called, provided the associated image does not
code. have multiple frames.
Pillow cannot in general close and reopen a file, so any access to Pillow cannot in general close and reopen a file, so any access to
that file needs to be prior to the close. that file needs to be prior to the close.
@ -41,12 +41,6 @@ that file needs to be prior to the close.
Issues 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 * Using the file context manager to provide a file-like object to
Pillow is dangerous unless the context of the image is limited to Pillow is dangerous unless the context of the image is limited to
the context of the file. the context of the file.
@ -54,20 +48,20 @@ The current open file handling is inconsistent at best:
Image Lifecycle Image Lifecycle
--------------- ---------------
* ``Image.open()`` called. Path-like objects are opened as a * ``Image.open()`` Path-like objects are opened as a file. Metadata is read
file. Metadata is read from the open file. The file is left open for from the open file. The file is left open for further usage.
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 required, ``load()`` is called. The current frame is read into
memory. The image can now be used independently of the underlying memory. The image can now be used independently of the underlying
image file. image file.
* ``Image.Image.seek()`` in the case of multi-frame images If a filename or a path-like object was passed to ``Image.open()``, then
(e.g. multipage TIFF and animated GIF) the image file left open so the file object was opened by Pillow and is considered to be used exclusively
that seek can load the appropriate frame. When the last frame is by Pillow. So if the image is a single-frame image, the file will
read, the image file is closed (at least in some image plugins), and be closed in this method after the frame is read. If the image is a
no more seeks can occur. 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 * ``Image.Image.close()`` Closes the file pointer and destroys the
core image object. This is used in the Pillow context manager core image object. This is used in the Pillow context manager
@ -77,16 +71,13 @@ Image Lifecycle
... # image operations here. ... # 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 must remain open until the ``load()`` or ``close()`` function is
called. called.
Multi-frame images are more complicated. The ``load()`` method is not Multi-frame images are more complicated. The ``load()`` method is not
a terminal method, so it should not close the underlying file. The a terminal method, so it should not close the underlying file. In general,
current behavior of ``seek()`` closing the underlying file on Pillow does not know if there are going to be any requests for additional
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
data until the caller has explicitly closed the image. 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 * Users of the library should call ``Image.Image.close()`` on any
multi-frame image to ensure that the underlying file is closed. multi-frame image to ensure that the underlying file is closed.

View File

@ -827,8 +827,10 @@ class Image(object):
Image class automatically loads an opened image when it is Image class automatically loads an opened image when it is
accessed for the first time. accessed for the first time.
This method will close the file associated with the image. See If the file associated with the image was opened by Pillow, then this
:ref:`file-handling` for more information. 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. :returns: An image access object.
:rtype: :ref:`PixelAccess` or :py:class:`PIL.PyAccess` :rtype: :ref:`PixelAccess` or :py:class:`PIL.PyAccess`