运行 Django 应用程序(使用 Gunicorn)时,我在 Heroku 上遇到内存问题。
我有以下代码,它获取用户上传的图像,删除所有 EXIF 数据,并返回准备上传到 S3 的图像。这既可以用作表单数据清理器,也可以在将 Base64 数据读入内存时使用。
def sanitise_image(img): # img is InMemoryUploadedFile
try:
image = Image.open(img)
except IOError:
return None
# Move all pixel data into a new PIL image
data = list(image.getdata())
image_without_exif = Image.new(image.mode, image.size)
image_without_exif.putdata(data)
# Create new file with image_without_exif instead of input image.
thumb_io = StringIO.StringIO()
image_without_exif.save(thumb_io, format=image.format)
io_len = thumb_io.len
thumb_file = InMemoryUploadedFile(thumb_io, None, strip_tags(img.name), img.content_type,
io_len, None)
# DEL AND CLOSE EVERYTHING
thumb_file.seek(0)
img.close()
del img
thumb_io.close()
image_without_exif.close()
del image_without_exif
image.close()
del image
return thumb_file
我基本上获取一个 InMemoryUploadedFile 并返回一个仅包含像素数据的新文件。
del
和 close
可能是多余的,但它们代表了我尝试修复 Heroku 内存使用量不断增长并且每次该函数终止时都不会释放的情况,甚至过夜:
在本地主机上使用 Guppy 运行它按照教程,堆中没有剩余的 InMemoryUploadedFile
、StringIO
和 PIL Image
,这让我很困惑。
我怀疑Python不会将内存释放回操作系统,正如我在多线程中读到的那样。有没有人玩过 InMemoryUploadedFile
并且可以给我解释为什么这个内存没有被释放?
当我不执行此清理操作时,不会出现此问题。
非常感谢!
最佳答案
我认为问题在于创建临时列表对象:
data = list(image.getdata())
尝试:
image_without_exif.putdata(image.getdata())
这就是为什么我认为这就是问题所在:
>>> images = [Image.new('RGBA', (100, 100)) for _ in range(100)]
Python 内存使用量增加了约 4Mb。
>>> get_datas = [image.getdata() for image in images]
没有内存增加。
>>> pixel_lists = [list(image.getdata()) for image in images]
Python 内存使用量增加了约 85Mb。
除非您明确需要数字,否则您可能不想将 getdata() 放入列表中。从枕头上docs :
Note that the sequence object returned by this method is an internal PIL data type, which only supports certain sequence operations. To convert it to an ordinary sequence (e.g. for printing), use list(im.getdata()).
关于python - Heroku Web dyno 运行 Django 应用程序不释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43210395/