Python IMAP搜索,搜索结果耗尽所有内存

时间:2011-10-27 09:01:47

标签: python search imaplib

我正在尝试使用imaplib从Python中的特定地址获取所有自动回复电子邮件。一切都运行好几个星期,但现在每次运行我的程序我的所有RAM都被消耗(几GB!)并且脚本最终被OOM杀手杀死。

以下是我目前正在使用的代码:

M = imaplib.IMAP4_SSL('server')
M.LOGIN('user', 'pass')
M.SELECT()
date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y")
result, data = M.uid('search', None, '(SENTON %s HEADER FROM "auto@site.com" NOT SUBJECT "RE:")' % date)
...

我确信应该返回少于100封几千字节的电子邮件。这可能是什么问题?或者有没有办法限制返回的电子邮件数量? THX!

1 个答案:

答案 0 :(得分:0)

无法确定原因是什么,无法重现问题(当然也没有看到触发问题的完整程序,并且知道您正在使用的所有依赖项的版本)。< / p>

但是,这是我最好的猜测。几个版本的Python包含了一个非常浪费内存的imaplib实现。这个问题在Windows上尤其明显,但不限于该平台。

问题的核心是从套接字读取时分配字符串的方式,以及imaplib从套接字读取字符串的方式。

从套接字读取时,Python首先分配一个足够大的缓冲区来处理应用程序要求的字节数。这听起来可能是合理的,也许是16 kB。然后将数据读入该缓冲区并缓冲区 down 以调整实际读取的字节数。

此操作的效率取决于平台重新分配实施的质量。调整缓冲区大小可能最终将其移动到更合适的位置,其中较小的大小避免浪费大量内存。或者它可能只是标记内存的尾部,不再作为该区域的一部分分配,可重复使用(甚至可以在实践中重复使用它)。或者它可能最终浪费技术上未分配的内存。

想象一下,如果你必须读取几十几KB的数据就会浪费内存的累积效应,并且数据一次从网络到达几十个字节。更糟糕的是,想象一下,如果数据真的很涓涓细流,你一次只能获得几个字节。或者,如果您正在读取几百KB的非常“大”响应。

浪费的内存量 - 由进程有效分配,但不能以任何有意义的方式使用 - 可能是巨大的。 100 kB数据,一次读取5个字节需要20480个缓冲区。如果每个缓冲区以16 kB开始并且未成功收缩,导致它们保持为16Kb,那么您已经分配了至少320MB的内存来保存100 kB的数据

某些版本的imaplib通过引入多层缓冲和复制来加剧这一问题。一个非常旧的版本(希望不是你实际使用的版本)甚至一次读取1个字节(在上面的场景中会导致1.6GB的内存使用量)。

当然,这个问题通常并没有出现在Linux上,其中重新分配器并不是那么糟糕。在以前的Python版本中(在最新的2.x版本之前的版本中)的各个点上,该错误是“修复的”,所以我不希望这些日子看到它出现。这并没有解释为什么你的程序在失败之前运行了一段时间。

但这是我最好的猜测。