第十七章:运行时特性-gc:垃圾回收器-跟踪引用

17.6 gc:垃圾回收器
gc提供了Python的底层内存管理机制,即自动垃圾回收器。这个模块包括一些函数,可以控制回收器如何操作,以及如何检查系统已知的对象,这些对象可能在等待收集,也可能已陷入引用环而无法释放。

17.6.1 跟踪引用
利用gc,可以使用对象之间来回的引用来查找复杂数据结构中的环。如果已知一个数据结构中存在环,那么可以使用定制代码来检查它的属性。如果环在未知代码中,则可以使用get_referents()和get_referrers)_函数建立同样的调试工具。
例如,get_referents()显示了输入参数引用的对象。

import gc
import pprint

class Graph:

    def __init__(self,name):
        self.name = name
        self.next = None

    def set_next(self,next):
        print('Linking nodes {}.next = {}'.format(self,next))
        self.next = next

    def __repr__(self):
        return '{}({})'.format(
            self.__class__.__name__,self.name)


# Construct a graph cycle.
one = Graph('one')
two = Graph('two')
three = Graph('three')

one.set_next(two)
two.set_next(three)
three.set_next(one)

print()
print('three refers to:')
for r in gc.get_referents(three):
    pprint.pprint(r)

在这里,Graph实例three包含其实例字典(在__dict__属性中)以及其类的引用。
在这里插入图片描述
下一个例子使用一个Queue来对所有对象引用完成一个广度优先遍历,以查找环。插入到队列中的元素为元组,其中包含目前为止的引用链和下一个要检查的对象。检查从three开始,要查看它引用的所有对象。跳过类意味着不检查它的方法、模块和其他组件。

import gc
import pprint
import queue


class Graph:

    def __init__(self,name):
        self.name = name
        self.next = None

    def set_next(self,next):
        print('Linking nodes {}.next = {}'.format(self,next))
        self.next = next

    def __repr__(self):
        return '{}({})'.format(
            self.__class__.__name__,self.name)


# Construct a graph cycle.
one = Graph('one')
two = Graph('two')
three = Graph('three')
one.set_next(two)
two.set_next(three)
three.set_next(one)

print()

seen = set()
to_process = queue.Queue()

# Start with an empty object chain and Graph three.
to_process.put(([],three))

# Look for cycles,building the object chain for each object
# found in the queue so the full cycle can be printed at the
# end.
while not to_process.empty():
    chain,next = to_process.get()
    chain = chain[:]
    chain.append(next)
    print('Examining:',repr(next))
    seen.add(id(next))
    for r in gc.get_referents(next):
        if isinstance(r,str) or isinstance(r,type):
            # Ignore serings and classes.
            pass
        elif id(r) in seen:
            print()
            print('Found a cycle to {}:'.format(r))
            for i,link in enumerate(chain):
                print('  {}: '.format(i),end=' ')
                pprint.pprint(link)
        else:
            to_process.put((chain,r))

通过监视已处理的对象,可以狠容易地发现节点中的环。所以这些对象的引用不会被收集,它们的id()值会缓存在一个集合中。环中找到的字典对象是Graph实例的__dict__值,其包括它们的实例属性。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值