在python中,当一个变量不被引用的时候就会触发垃圾回收机制从而被从内存中删除,但有时一个不注意可能就会出现内存泄漏问题。
Python中可能的会出现内存泄露的情况
(1) 循环引用:当两个或多个对象相互引用,造成的循环引用进而导致内存泄露
(2) 大量创建对象:当程序中频繁创建大量的对象并没有及时销毁,也会导致内存泄露
(3) 全局变量:当全局变量被创建后一直存在,即使它们不再被使用,也会占用内存空间,可能导致内存泄露
(4) 不适当的缓存使用:如果在缓存中存储了大量数据,而没有适当地删除旧数据,会导致内存泄漏
(5) C扩展模块:使用C扩展模块编写的代码可能会出现内存泄漏问题,因为C扩展代码不受Python的垃圾回收机制控制
(6) 超大型文件(上T)的读写操作
(7) 没有正确关闭文件或网络套接字:如果在使用完文件或网络套接字后不将其正确关闭,可能会导致内存泄漏
那么我们如果发现了内存泄漏(内存占用一直在涨,直到最终程序报MemoryError),该如何去找到导致内存泄漏的代码呢?
1、安装memory-profiler
首先在cmd中
pip install memory-profiler -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com
2、导入memory-profiler
在要查bug的代码py文件中,开头输入
from memory_profiler import profile
在要测试的函数前加装饰器(注意是在函数前,也就是如果函数只被调用一次,生成的记录就只会有那一次的)
@profile(precision=4,stream=open('log.txt','w+',encoding="utf-8"))
参数含义:
precision:精确到小数点后几位
stream:此模块分析结果保存到 'memory_profiler.log' 日志文件。如果没有此参数,分析结果会在控制台输出
3、运行我们的py文件
memory_profiler.log文件中即可显示每一行的内存情况。从而定位到底是哪一行开始发生了内存改变。
Linux:
python -m memory_profiler memory_profiler_test.py
windows:
直接运行py文件就行
log文件中是这样的:
Mem usage是当前行运行后的内存,Increment是当前行运行后增加的内存。
此时大致能知道是哪个操作增加了内存,后续却没有被释放掉(调别的函数发现内存没变回原来的)。找到这个有问题的变量。
4.只有当地址没有任何引用时,才会被释放,如何查看地址的引用情况
from sys import getrefcount
a = [1,2,3]
print(getrefcount(a)) #输出:2
b = a
print(getrefcount(b)) #输出:3