python-python内存泄露跟踪

最近被python的内存使用搞得比较的郁闷,记录在案。

 

内存泄漏的经典定义是曾经使用过一次的内存,现在却没有,但还没有被回收。使用纯Python代码几乎不可能。但正如Antoine指出的那样,即使您不需要保留所有数据,您也可以通过允许数据结构无限制地增长来轻松地消耗所有内存。

1 将值存储在类或全局范围而不是实例范围中,而不是实现它。

比如下面的这个代码:

class Money(object):
    name = ''
    symbols = []   # This is the dangerous line here

    def set_name(self, name):
        self.name = name

    def add_symbol(self, symbol):
        self.symbols.append(symbol)


m = Money()
m.set_name('Dollar')
m.add_symbol('$')

那么正确的写法应该是如何呢?

class Money(object):
    self.name = ''
    self.symbols = []   # This is the dangerous line here

    def set_name(self, name):
        self.name = name

    def add_symbol(self, symbol):
        self.symbols.append(symbol)

2 sys.exc_info()带来的循环引用

问题代码如下:

while game.running():
    try:
        key_press = handle_input()
    except SomeException:
        etype, evalue, tb = sys.exc_info()
        # Do something with tb like inspecting or printing the traceback

这里面我们可能认为tb是一个临时变量,但是实际上,tb包含了handle_input运行的上下文信息。如果game一直在执行中,那么tb依然不会被释放,哪怕是下一次执行handle_input。

3 在类中自己实现__del__方法

class ClientConnection(...):
    def __del__(self):
        if self.socket is not None:
            self.socket.close()
            self.socket = None
现在这个工作正常,你可能会认为它是操作系统资源的良好管理者,以确保套接字被“处置”。

但是,如果ClientConnection保留引用说明,用户和用户保留对连接的引用,您可能会想要说清理时,让用户取消引用连接。这实际上是一个缺陷:循环GC不知道正确的操作顺序,也无法清理它。

对此的解决方案是确保你通过调用某种类型的关闭来断开事件,但是将该方法命名为__del__以外的其他方法。

4 非正常使用C库

 

在Python中,您相信垃圾收集器会丢弃您不使用的内容。但是,如果使用包装C库的C扩展,则大多数时候您负责确保明确关闭或取消分配资源。大多数情况下都记录了这一点,但是习惯于不必进行此显式取消分配的python程序员可能会丢弃句柄(如从函数或其他任何内容返回)到该库而不知道资源被保留。

 

 

 

 

 

【参考文献】

【1】https://stackoverflow.com/questions/2017381/is-it-possible-to-have-an-actual-memory-leak-in-python-because-of-your-code

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值