如何找出使用PIL函数导致内存错误的原因?

13 投票
2 回答
4878 浏览
提问于 2025-04-17 04:17

我正在使用PIL(Python图像库)来处理一些图像,具体来说,我是在拼接图像。

我的代码在处理少量小图像时似乎运行得很好,但有时我会遇到一个MemoryError的错误。

让我感到特别奇怪的是,我并没有在处理大图像,所有的图像都小于10张,且每张图像的大小都在10KB以下。

我调用了很多次Image.resize,但我很惊讶这会导致这么大的问题。

以下是错误的堆栈跟踪信息:

Traceback (most recent call last):                                                                                                                                               
  File "test.py", line 15, in <module>                                                                                                                                           
    pprint(scale_matrix_down((90,90), [inpt]))                                                                                                                                   
  File "/Users/jeremykarmel/Desktop/Python/merger.py", line 105, in scale_matrix_down                                                                                            
    return [shrinkRow(row, row_width_overflow(row)) for row in matrix]                                                                                                           
  File "/Users/jeremykarmel/Desktop/Python/merger.py", line 103, in shrinkRow                                                                                                    
    rest         = [shrinkIm(im, pixels_per_im) for im in row[remaining_pixels:]]                                                                                                
  File "/Users/jeremykarmel/Desktop/Python/merger.py", line 110, in shrinkIm                                                                                                     
    return im.resize((im.size[0] - num_pix, im.size[1] - num_pix))                                                                                                               
  File "/Library/Python/2.7/site-packages/PIL/Image.py", line 1302, in resize                                                                                                    
    im = self.im.resize(size, resample)                                                                                                                                          
MemoryError

请记住,这些图像的尺寸都小于90x90像素。

我现在真的遇到了瓶颈,不知道该怎么继续。有什么办法可以释放内存吗?我应该使用del操作符,还是有更简单的方法可以解决这个问题?非常感谢你的帮助!

2 个回答

8

其实这并不是一个内存错误。正如Winston Ewert指出的,我实际上是把负数参数传给了图像的缩放方法。

虽然Python的文档说内存错误是和内存问题有关,但当你给缩放方法传负数参数时,也会出现这个错误。我猜是因为PIL这个库大量使用了C语言的库,这可能会因为无效的输入导致一些问题,而且这个库没有进行边界检查,所以错误就直接冒出来了。

10

来解释一下实际发生了什么:

  1. 你试图把一张图片的宽度调整为负值。
  2. PIL(一个处理图像的库)试着为这个负宽度的图片分配空间。
  3. PIL 调用 malloc(一个用来申请内存的函数),但是它请求的内存大小是负数。
  4. malloc 只接受无符号的大小(也就是不能是负数),所以它把这个负数当成了一个非常大的数字来处理。
  5. malloc 不能分配这么大的内存,所以它就报错了。
  6. 对 PIL 来说,这个错误看起来就像是内存不够用,所以它也把这个错误报告成内存不足。

所以,输入的错误并没有导致内存泄漏或其他不好的行为。它们只是导致了一个错误的内存请求,然后就放弃了。PIL 本可以检查一下是否有负值的情况,这样就能给出更好的错误提示。不过他们可能觉得没必要,因为如果真的出现这种情况,已经会报错了。

实际上,真正用完内存是很难的,因为操作系统会努力保持程序运行,比如使用虚拟内存。在你系统变得很慢之前,通常不会真的用完内存。因此,我发现大多数内存不足的错误都是因为请求了负数的内存。就我记得的来说,我在 Java 中遇到的真正的内存不足错误可能是由于它使用了虚拟机。

撰写回答