python list 内存泄漏_05 python内存泄漏

python内存泄露

起因

内存泄露指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。导致程序运行速度减慢甚至系统崩溃等严重后果。有 del() 函数的对象间的循环引用是导致内存泄漏的主凶

方案

不使用一个对象时使用:delobject 来删除一个对象的引用计数就可以有效防止内存泄漏问题。通过Python 扩展模块 gc 来查看不能回收的对象的详细信息。可以通过 sys.getrefcount(obj) 来获取对象的引用计数,并根据返回值是否为 0 来判断是否内存泄漏。

但是由于gc垃圾收集机制,要遍历所有被垃圾收集器管理的python对象(包括垃圾和非垃圾对象),该过程比较耗时可能会造成程序卡顿,会对某些对内存、cpu要求较高的场景造成性能影响。那怎么才能优雅地避免内存泄露呢?

编写安全的代码

比如对于下面发生内存泄露的cycle_ref函数,在函数结束前解除循环引用,即可解决内存泄露问题。

def cycle_ref():

a1 = A()

a2 = A()

a1.child = a2

a2.child = a1

# 解除循环引用,避免内存泄露

a1.child = None

a2.child = None

但是对于上述方法,我们有可能会忘记那一两行无关紧要的代码而造成灾难性后果,毕竟老虎也有打盹的时候。那怎么办?不要着急,Python已经为我们考虑到这点:弱引用。

弱引用

Python标准库提供了weakref模块,弱引用不会在引用计数中计数,其主要目的是解决循环引用。并非所有的对象都支持weakref,例如list和dict就不支持。下面是weakref比较常用的方法:

"""

1. class weakref.ref(object[, callback]) :创建一个弱引用对象,object是被引用的对象,callback是回调函数(当被引用对象被删除时,调用该回调函数)

2.weakref.proxy(object[, callback]):创建一个用弱引用实现的代理对象,参数同上

3.weakref.getweakrefcount(object) :获取对象object关联的弱引用对象数

4.weakref.getweakrefs(object):获取object关联的弱引用对象列表

5.class weakref.WeakKeyDictionary([dict]):创建key为弱引用对象的字典

6.class weakref.WeakValueDictionary([dict]):创建value为弱引用对象的字典

7.class weakref.WeakSet([elements]):创建成员为弱引用对象的集合对象

"""

同样对于上面发生内存泄露的cycle_ref函数,使用weakref稍加改造,便可更安全地解决内存泄露问题:

import weakref

class A(object):

def __init__(self):

self.data = [x for x in range(100000)]

self.child = None

def __del__(self):

pass

def cycle_ref():

a1 = A()

a2 = A()

a1.child = weakref.proxy(a2)

a2.child = weakref.proxy(a1)

if __name__ == '__main__':

import time

while True:

time.sleep(0.5)

cycle_ref()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值