mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-10 19:56:47 +03:00
Merge pull request #551 from wiredfool/with
Image.close, Context manager support
This commit is contained in:
commit
5ca5652d0b
43
PIL/Image.py
43
PIL/Image.py
|
@ -92,7 +92,7 @@ except ImportError:
|
|||
|
||||
from PIL import ImageMode
|
||||
from PIL._binary import i8, o8
|
||||
from PIL._util import isPath, isStringType
|
||||
from PIL._util import isPath, isStringType, deferred_error
|
||||
|
||||
import os, sys
|
||||
|
||||
|
@ -497,6 +497,35 @@ class Image:
|
|||
|
||||
_makeself = _new # compatibility
|
||||
|
||||
# Context Manager Support
|
||||
def __enter__(self):
|
||||
return self
|
||||
def __exit__(self, *args):
|
||||
self.close()
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Closes the file pointer, if possible.
|
||||
|
||||
This operation will destroy the image core and release it's memory.
|
||||
The image data will be unusable afterward.
|
||||
|
||||
This function is only required to close images that have not
|
||||
had their file read and closed by the
|
||||
:py:meth:`~PIL.Image.Image.load` method.
|
||||
"""
|
||||
try:
|
||||
self.fp.close()
|
||||
except Exception as msg:
|
||||
if Image.DEBUG:
|
||||
print ("Error closing: %s" %msg)
|
||||
|
||||
# Instead of simply setting to None, we're setting up a
|
||||
# deferred error that will better explain that the core image
|
||||
# object is gone.
|
||||
self.im = deferred_error(ValueError("Operation on closed image"))
|
||||
|
||||
|
||||
def _copy(self):
|
||||
self.load()
|
||||
self.im = self.im.copy()
|
||||
|
@ -642,7 +671,8 @@ class Image:
|
|||
Allocates storage for the image and loads the pixel data. In
|
||||
normal cases, you don't need to call this method, since the
|
||||
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.
|
||||
|
||||
:returns: An image access object.
|
||||
"""
|
||||
|
@ -2074,10 +2104,11 @@ def open(fp, mode="r"):
|
|||
"""
|
||||
Opens and identifies the given image file.
|
||||
|
||||
This is a lazy operation; this function identifies the file, but the
|
||||
actual image data is not read from the file until you try to process
|
||||
the data (or call the :py:meth:`~PIL.Image.Image.load` method).
|
||||
See :py:func:`~PIL.Image.new`.
|
||||
This is a lazy operation; this function identifies the file, but
|
||||
the file remains open and the actual image data is not read from
|
||||
the file until you try to process the data (or call the
|
||||
:py:meth:`~PIL.Image.Image.load` method). See
|
||||
:py:func:`~PIL.Image.new`.
|
||||
|
||||
:param file: A filename (string) or a file object. The file object
|
||||
must implement :py:meth:`~file.read`, :py:meth:`~file.seek`, and
|
||||
|
|
|
@ -89,8 +89,8 @@ try:
|
|||
except ImportError as ex:
|
||||
# Allow error import for doc purposes, but error out when accessing
|
||||
# anything in core.
|
||||
from _util import import_err
|
||||
_imagingcms = import_err(ex)
|
||||
from _util import deferred_error
|
||||
_imagingcms = deferred_error(ex)
|
||||
from PIL._util import isStringType
|
||||
|
||||
core = _imagingcms
|
||||
|
|
|
@ -15,7 +15,7 @@ else:
|
|||
def isDirectory(f):
|
||||
return isPath(f) and os.path.isdir(f)
|
||||
|
||||
class import_err(object):
|
||||
class deferred_error(object):
|
||||
def __init__(self, ex):
|
||||
self.ex = ex
|
||||
def __getattr__(self, elt):
|
||||
|
|
|
@ -2,6 +2,8 @@ from tester import *
|
|||
|
||||
from PIL import Image
|
||||
|
||||
import os
|
||||
|
||||
def test_sanity():
|
||||
|
||||
im = lena()
|
||||
|
@ -9,3 +11,17 @@ def test_sanity():
|
|||
pix = im.load()
|
||||
|
||||
assert_equal(pix[0, 0], (223, 162, 133))
|
||||
|
||||
def test_close():
|
||||
im = Image.open("Images/lena.gif")
|
||||
assert_no_exception(lambda: im.close())
|
||||
assert_exception(ValueError, lambda: im.load())
|
||||
assert_exception(ValueError, lambda: im.getpixel((0,0)))
|
||||
|
||||
def test_contextmanager():
|
||||
fn = None
|
||||
with Image.open("Images/lena.gif") as im:
|
||||
fn = im.fp.fileno()
|
||||
assert_no_exception(lambda: os.fstat(fn))
|
||||
|
||||
assert_exception(OSError, lambda: os.fstat(fn))
|
||||
|
|
|
@ -126,8 +126,8 @@ Identify Image Files
|
|||
|
||||
for infile in sys.argv[1:]:
|
||||
try:
|
||||
im = Image.open(infile)
|
||||
print(infile, im.format, "%dx%d" % im.size, im.mode)
|
||||
with Image.open(infile) as im:
|
||||
print(infile, im.format, "%dx%d" % im.size, im.mode)
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
|
|
|
@ -136,9 +136,9 @@ ITU-R 709, using the D65 luminant) to the CIE XYZ color space:
|
|||
.. automethod:: PIL.Image.Image.verify
|
||||
|
||||
.. automethod:: PIL.Image.Image.fromstring
|
||||
.. deprecated:: 2.0
|
||||
|
||||
.. automethod:: PIL.Image.Image.load
|
||||
.. automethod:: PIL.Image.Image.close
|
||||
|
||||
Attributes
|
||||
----------
|
||||
|
|
Loading…
Reference in New Issue
Block a user