Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4562006
  • 博文数量: 1214
  • 博客积分: 13195
  • 博客等级: 上将
  • 技术积分: 9105
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
个人简介

C++,python,热爱算法和机器学习

文章分类

全部博文(1214)

文章存档

2021年(13)

2020年(49)

2019年(14)

2018年(27)

2017年(69)

2016年(100)

2015年(106)

2014年(240)

2013年(5)

2012年(193)

2011年(155)

2010年(93)

2009年(62)

2008年(51)

2007年(37)

分类: Python/Ruby

2020-12-01 10:14:45

https://blog.csdn.net/TiffanyRabbit/article/details/80580056

提到python,很多人的第一直觉大概就是爬虫和网络相关。然而最近使用python2.7 urllib2和request的时候却无意中发现可能存在严重的内存泄漏问题,或者说垃圾回收有问题。stackoverflow了一下,确实有很多人反应了相关的问题,至今还没解决。综合了各种解决方案,最终确定了一种临时的替代方案,在此记录和分享。

问题介绍 & 重现

用过python进行大量网络请求的童鞋,可能都会发现,当请求达到一定量之后会出现内存问题,无法再进行请求。下面,我们用利用python内置的gc库看一下urllib2和request请求过后的内存回收情况。

import gc, urllib, urllib2, requests def get_unreachable_memory_len(): # check memory on memory leaks gc.set_debug(gc.DEBUG_SAVEALL)
    gc.collect()
    unreachableL = [] for it in gc.garbage:
        unreachableL.append(it) print str(unreachableL) return len(str(unreachableL)) def request_with_urllib2(url): resp = urllib2.urlopen(url) return resp.read() def request_with_requests(url): resp = requests.get(url) return resp.content
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

启动python,先调用一下get_unreachable_memory_len()看一下当前有没有内存泄露:
这里写图片描述
返回是为空,证明没有memory leak.

运行request_with_urllib2('')之后我们拿到了长度为41536的胡歌歌的照片:
这里写图片描述 但不幸的是,我们看内存:
这里写图片描述
由于网络请求没有被正确回收,导致内存出现了一定的泄露,这部分泄露是response中没有被处理的部分。

同理我们再试一下request_with_requests('')
这里写图片描述
这里写图片描述
同样,在进行requests.get后,内存回收也出现了问题。

解决方案

在若干次实验后,终于找到了较为理想的解决方案,也就是暂时用urllib+contextlib.closing的组合进行临时替代。这样可以在不换掉python2.7的条件下,实现不伤害内存的网络请求。

from contextlib import closing def url_request(url): # request without memory leak res = None with closing(urllib.urlopen(url)) as resp:
        res = resp.read() return res
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

同样的方法,我们来试一下这种方案。(注意此处要重启一个新的python shell测试哦~)

get_unreachable_memory_len() url_request('') get_unreachable_memory_len()
  • 1
  • 2
  • 3

这里写图片描述
从图片中我们可以清楚的看到,通过url_request我们不仅获取了胡歌歌的大图,还完成了完整的response回收,通过gc检查内存也没有任何问题。妥妥的解决~

阅读(1211) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~