【问题标题】:Pillow+numpy+unittest gives a ResourceWarning: does this indicate a leak?Pillow+numpy+unittest 给出了 ResourceWarning:这是否表示泄漏?
【发布时间】:2016-07-23 12:21:53
【问题描述】:

当我在 Python3 上使用 Pillow(版本 3.3.0,通过 pip 安装)将图像数据加载到 numpy 数组中时,我的单元测试报告了 ResourceWarning。例如,当我运行以下脚本时会出现警告:

#! /usr/bin/env python3

import unittest
import numpy as np
import PIL.Image

def load_image():
    with PIL.Image.open('test.tif') as im:
        return np.array(im)

class TestData(unittest.TestCase):

    def test_PIL(self):
        im = load_image()
        print(im.shape)

unittest.main()

输出是

./err.py:14: ResourceWarning: unclosed file <_io.BufferedReader name='test.tif'>
  im = load_image()
(420, 580)
.
----------------------------------------------------------------------
Ran 1 test in 0.012s

OK

(如果我不将图像包装在 numpy 数组中,警告就会消失。)

此资源警告是否表明我的代码中有泄漏(例如,除了使用 with 语句之外,我是否需要以某种方式“关闭”图像文件)?或者,如果警告是虚假的,我该如何禁用它?

【问题讨论】:

  • 如果你使用np.array(im.getdata())会怎样?
  • @WayneWerner using np.array(im.getdata()) 我仍然收到警告,而且数组的形状也错误。

标签: python-3.x numpy pillow


【解决方案1】:

TL;DR,我认为这是一个错误。这应该会按预期关闭文件句柄:

def load_image():
    with open('test.tif', 'rb') as im_handle:
        im = PIL.Image.open(im_handle)
        return np.array(im)

好的,让我们看看实际发生了什么:

为此我们添加了一个记录器:

#! /usr/bin/env python3

import logging
logging.getLogger().setLevel(logging.DEBUG)
logging.debug('hi from the logger!')

import unittest
import numpy as np
import PIL.Image

def load_image():
    with PIL.Image.open('test.tif') as im:
        return np.array(im)

class TestData(unittest.TestCase):

    def test_PIL(self):
        im = load_image()
        print(im.shape)

unittest.main()

这是我们得到的:

DEBUG:root:hi from the logger!
/Users/ch/miniconda/envs/sci34/lib/python3.4/site-packages/PIL/Image.py:678: ResourceWarning: unclosed file <_io.BufferedReader name='test.tif'>
  self.load()
DEBUG:PIL.Image:Error closing: 'NoneType' object has no attribute 'close'
(225, 300, 3)
.
----------------------------------------------------------------------
Ran 1 test in 0.022s

OK

DEBUG:PIL.Image:Error closing: 'NoneType' object has no attribute 'close'Image 类的 close 方法中引发:

def close(self):
    """
    Closes the file pointer, if possible.

    This operation will destroy the image core and release its 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:
        logger.debug("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"))

用一句话来形容:

with 块的末尾,调用close 方法。它尝试关闭存储在self.fp 中的打开文件句柄。但在您的情况下,self.fp 不是文件句柄,因此无法关闭。关闭无声无息。

所以当你离开with块时,文件句柄没有关闭,鼻子的错误信息是合法的。

【讨论】:

  • 谢谢,我同意您的分析,并且您的解决方法有效。我还考虑为 Pillow 提交一个错误,但他们已经有几份报告似乎是同一个问题,所以我只是在 github.com/python-pillow/Pillow/issues/1651 留下了一个便条。
猜你喜欢
  • 2011-01-16
  • 2012-01-23
  • 1970-01-01
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
  • 1970-01-01
  • 2010-11-25
  • 2018-04-28
相关资源
最近更新 更多