python内存泄露的原因是什么

像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题。在Python程序里,内存泄漏是由于一个长期持有的对象不断的往一个dict或者list对象里添加新的对象, 而又没有即时释放,就会导致这些对象占用的内存越来越多,从而造成内存泄漏。另外,对象的交叉引用也会造成内存无法释放的问题。

那么如果在Python里发现了内存泄漏的问题,如何去查找呢?本文讲述了如何使用objgraph这个工具来进行内存泄漏的查找。

1、先下载objgraph这个工具:http://mg.pov.lt/objgraph/

https://pypi.python.org/pypi/objgraph

pythonsetup.py install,进行安装。

2、安装graphviz

这是一个将图结构转化成png图片表示的工具,有了它,就可以通过对象的引用关系,为最终找到内存泄漏的对方提供最好的指导。

windows版下载地址:http://www.graphviz.org/Download_windows.php

ubuntu下安装:

sudo apt-get install graphviz

这个工具还可以利用graphviz这个工具来生成可视化的对象引用关系图,但是根据个人的使用经验,在对象比较多的时候,生成的图往往会比较大。

3、如何查找产生泄漏的对象:

objgraph.show_growth()

这个函数可以说是这个工具中最有用的函数了,作用是输出增长的对象。

4、先从一个例子看看怎样用:

import os
import gc
import objgraph
gc.collect()
print'====================================='
objgraph.show_growth()
 
a = []
 
print'====================================='
objgraph.show_growth()
 
a.append([1,2,3])
 
print'====================================='
objgraph.show_growth()
 
b = ['a','b','c']
del b
 
print'===================================='
objgraph.show_growth()

输出如下:

=====================================
wrapper_descriptor            1020    +1020
function                      975      +975
builtin_function_or_method     615      +615
dict                          414      +414
method_descriptor             391      +391
weakref                       286      +286
member_descriptor             192      +192
tuple                         181      +181
list                          159      +159
getset_descriptor             132      +132
=====================================
wrapper_descriptor     1031      +11
member_descriptor      196        +4
getset_descriptor      135        +3
weakref               289        +3
dict                  417        +3
list                  160        +1
=====================================
list      161       +1
====================================

从打印可以看出:

第一次调用show_growth时,实际上打印出来的是当前所有对象的总数

第二次调用show_growth时,可以看到list对象增长了1,这正是a = []所创建的,其它增长的对象应该是在第一次调用show_growth函数内部产生的。

当调用a.append([1,2,3])后,再调用show_growth,又发现list对象增长了1个。

再接下来,调用b =['a','b','c'] 后又马上调用del b把这个对象删除,再调用show_growth时对象没有增长。

从上面的例子来看,show_growth可以准确的打印出增长的对象以及增长的个数。

在实际情况中,通常为了查找出哪些对象有内存泄漏,一般用每隔一段时间调用一次show_growth的方法,然后找出对象的个数一直在增长的对象,这些对象即为发生了内存泄漏的对象。

说明:为了使show_growth的输出更为准确,在调用show_growth时,最好调用gc.collect()进行一次垃圾对象的回收。

云海天教程网,大量的免费python教程,欢迎在线学习!

来源:PY学习网:原文地址:https://www.py.cn/article.html

hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » python内存泄露的原因是什么