如何找出使用PIL函数导致内存错误的原因?
我正在使用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
来解释一下实际发生了什么:
- 你试图把一张图片的宽度调整为负值。
- PIL(一个处理图像的库)试着为这个负宽度的图片分配空间。
- PIL 调用 malloc(一个用来申请内存的函数),但是它请求的内存大小是负数。
- malloc 只接受无符号的大小(也就是不能是负数),所以它把这个负数当成了一个非常大的数字来处理。
- malloc 不能分配这么大的内存,所以它就报错了。
- 对 PIL 来说,这个错误看起来就像是内存不够用,所以它也把这个错误报告成内存不足。
所以,输入的错误并没有导致内存泄漏或其他不好的行为。它们只是导致了一个错误的内存请求,然后就放弃了。PIL 本可以检查一下是否有负值的情况,这样就能给出更好的错误提示。不过他们可能觉得没必要,因为如果真的出现这种情况,已经会报错了。
实际上,真正用完内存是很难的,因为操作系统会努力保持程序运行,比如使用虚拟内存。在你系统变得很慢之前,通常不会真的用完内存。因此,我发现大多数内存不足的错误都是因为请求了负数的内存。就我记得的来说,我在 Java 中遇到的真正的内存不足错误可能是由于它使用了虚拟机。