请求库中的内存泄漏

时间:2014-07-09 14:18:36

标签: python python-requests

我注意到使用请求库检索pdf文件时内存使用量大幅增加。文件本身大约4MB,但分配给python进程的物理内存增加了超过150MB!

有人知道这种行为的可能原因(也许是修复)吗?

这是测试用例:

import requests,gc
def dump_mem():
  s = open("/proc/self/status").readlines()
  for line in s:
    if line.startswith("VmRSS"):
      return line

以下是我在intrepretter中得到的输出。

>>> gc.collect()
0
>>> dump_mem()
'VmRSS:\t   13772 kB\n'
>>> gc.collect()
0
>>> r = requests.get('http://www.ipd.uni-karlsruhe.de/~ovid/Seminare/DWSS05/Ausarbeitungen/Seminar-DWSS05')
>>> gc.collect()
5
>>> dump_mem()
'VmRSS:\t   20620 kB\n'
>>> r.headers['content-length']
'4089190'
>>> dump_mem()
'VmRSS:\t   20628 kB\n'
>>> gc.collect()
0
>>> c = r.content
>>> dump_mem()
'VmRSS:\t   20628 kB\n'
>>> gc.collect()
0
>>> t = r.text
>>> gc.collect()
8
>>> dump_mem()
'VmRSS:\t  182368 kB\n'

显然,我不应该尝试将pdf文件解码为文本。但无论如何,这种行为的原因是什么?

1 个答案:

答案 0 :(得分:3)

如果内容类型中不包含charset参数且响应 text/ mimetype,则使用字符检测库来确定编解码器。< / p>

使用response.text触发了这个检测,加载了库,它的模块包含了一些相当大的表。

根据您已安装的requests的确切版本,您会发现现在有sys.modules['requests.packages.chardet']sys.modules['requests.packages.charade']以及大约36个子模块,在你使用r.text之前。

当检测运行时,会创建许多在PDF文档中使用各种统计技术的对象,因为检测无法在任何特定编解码器上获得足够的确定性。为了使所有这些适合内存,Python要求从您的操作系统分配更多内存。一旦检测过程完成,该内存将再次释放,但操作系统然后取消分配该内存,而不是立即取消分配。这样做是为了防止疯狂的内存流失,因为进程可以轻松地请求并释放内存。

请注意,您r.text的结果添加到您的记忆中,并绑定到t。这是一个Unicode文本对象,在Python 2中占用的内存是bytestring对象的2到4倍。您在那里的特定下载将近4 MB作为字节字符串,但如果您使用的是UCS-4 Python构建,则生成的Unicode值仅为解码值添加另外16 MB