美文网首页
关于 Python 循环引用

关于 Python 循环引用

作者: whosemario | 来源:发表于2016-04-27 11:04 被阅读0次

python解决循环引用的逻辑还是比较简单,今晚写了一个脚本层的查找unreachable object的方法,模拟的就是查找循环引用的算法

# -*- coding:utf-8 -*-

import gc
import sys

REACHABLE = -10001
TENTATIVELY_UNREACHABLE = -10002

def get_unreachable_objects():

    # 1. update refs
    gc_refs = {}
    for obj in gc.get_objects():
        assert id(obj) not in gc_refs
        # 在这个过程中会增加三个引用
        # 1. 放入list一个引用
        # 2. obj一个引用
        # 3. 调用getrefcount(obj)会产生一个临时引用
        gc_refs[id(obj)] = sys.getrefcount(obj) - 3  
    obj = None

    # 2. substract refs
    for obj in gc.get_objects():
        for child in gc.get_referents(obj):
            if id(child) in gc_refs:
                gc_refs[id(child)] -= 1
        child = None
    obj = None

    # 3. get unreachable
    is_running = True
    while is_running:
        for obj in gc.get_objects():
            assert id(obj) in gc_refs
            if gc_refs[id(obj)] == REACHABLE:
                continue
            if gc_refs[id(obj)] > 0:
                gc_refs[id(obj)] = REACHABLE
                for child in gc.get_referents(obj):
                    if id(child) in gc_refs:
                        if gc_refs[id(child)] == 0:
                            gc_refs[id(child)] = 1
                        elif gc_refs[id(child)] == TENTATIVELY_UNREACHABLE:
                            gc_refs[id(child)] = 1
                        else:
                            assert gc_refs[id(child)] > 0 or gc_refs[id(child)] == REACHABLE
                child = None
            elif gc_refs[id(obj)] == 0:
                gc_refs[id(obj)] = TENTATIVELY_UNREACHABLE
            else:
                assert gc_refs[id(obj)] in (REACHABLE, TENTATIVELY_UNREACHABLE)
        obj = None

        is_running = False
        for v in gc_refs.itervalues():
            if v not in (REACHABLE, TENTATIVELY_UNREACHABLE):
                is_running = True
                break
        v = None

    unreachable = [k for k, v in gc_refs.iteritems() if v == TENTATIVELY_UNREACHABLE]

    ret = []
    for obj in gc.get_objects():
        if id(obj) in unreachable:
            ret.append(obj)
    obj = None
    return ret

if __name__ == "__main__":
    class A(object): pass
    a = A()
    b = A()
    c = A()
    b.v = c
    c.v = b
    b_id = id(b)
    a_id = id(c)
    a = None
    b = None
    c = None
    print get_unreachable_objects()
    gc.set_debug(gc.DEBUG_LEAK | gc.DEBUG_STATS)
    gc.collect()

脚本分为三步:

  • update_refs
  • substract refs
  • find unreachable objects

与Python GC的逻辑基本一样,目前在我们的开发服上测试还是有些问题

相关文章

  • 关于 Python 循环引用

    python解决循环引用的逻辑还是比较简单,今晚写了一个脚本层的查找unreachable object的方法,模...

  • iOS 循环引用

    关于循环引用看着3篇文章就够了,拿走不谢! 循环引用 循环引用 OC中的block OC中的block 关于 bl...

  • 关于循环引用

    转:https://www.jianshu.com/p/51bb714051ea 谈到循环引用,不知道你能想到什么...

  • python循环引用问题

  • iOS中NSTimer循环引用

    关于这种NSTimer,如果是 repeat = YES 的定时器,没有处理就会出现循环引用的问题。关于循环引用的...

  • 4-8 循环引用

    3种循环引用 自循环引用 相互循环引用 多循环引用 Block的循环引用 NSTimer 的循环引用 破除循环引用...

  • 关于block循环引用

    如果在block中使用附有__strong修饰符的对象类型自动变量,那么当block从栈区拷贝到堆区时,该对象为b...

  • 关于Block循环引用

    关于使用__weak和__strong 大家都看到别人在block里面使用self或者self的属性的时候要使用_...

  • 关于 循环引用问题

    一.概述 多个对象相互持有,A对象强引用B对象,同时B对象也强引用于A对象,两者相互等待对方发消息告诉自己需要Re...

  • 循环引用的相关问题

    1、循环引用的种类(1)自循环引用(2)相互循环引用(3)多循环引用 如何破除循环引用?(1)避免产生循环引用(2...

网友评论

      本文标题:关于 Python 循环引用

      本文链接:https://www.haomeiwen.com/subject/nsfcrttx.html