Python垃圾回收之循环引用

本文探讨了Python中的内存泄露问题,特别是由于全局变量引用和循环引用导致的情况。介绍了Python的垃圾回收机制,包括引用计数、分代收集和标记清除。详细阐述了可达性和不可达对象的概念,并讲解了如何使用GC模块进行调试,如设置DEBUG_COLLETABLE和DEBUG_UNCOLLETABLE标志。从Python 3.4开始,PEP442使得带有方法的循环引用能得到自动处理,减少了内存泄露的发生。

什么情况存在内存泄露

  • python引用计数 + 分代收集和标记清除(处理循环引用),进行垃圾回收,但如下两种情况依旧存在内存泄露:
  • 第一是对象被另一个生命周期特别长(如全局变量)的对象所引用
  • 第二是循环引用中的对象定义了__del__函数,简而言之,循环引用中Python无法判断析构对象的顺序,无法释放

相关术语

  • reachable/collectable(unreachable/uncollectable)
  • reachable是针对python对象而言,如果从根集(root)能到找到对象,那么这个对象就是reachable,与之相反就是unreachable,unreachable只存在于循环引用中的对象,Python的gc模块就是针对unreachable对象
  • collectable是针对unreachable对象而言,如果这种对象能被回收,是collectable,如果不能被回收,即循环引用中的对象定义了__del__, 那么就是uncollectable。 即unreachable (循环引用)分成 collectable和ubcollectable(__del__

GC模块

This module provides access to the garbage collector for reference cycles.
enable() -- Enable automatic garbage collection.
disable() -- Disable automatic garbage collection.
isenabled() -- Returns true if automatic collection is enabled.
collect() -- Do a full collection right now. Tg

gc.set_debug(flags)
gc.DEBUG_COLLETABLE: 打印可以被垃圾回收器回收的对象
gc.DEBUG_UNCOLLETABLE: 打印无法被垃圾回收器回收的对象,即定义了__del__的对象
gc.DEBUG_SAVEALL:所有的unreachable对象都将加入gc.garbage返回的列表
gc.garbage: 返回是unreachable对象,且不能被回收的的对象,如果设置SAVEALL,所有unreachable都加入此列表

A list of objects which the collector found to be unreachable but could not be freed (uncollectable objects). Starting with Python 3.4, this list should be empty most of the time, except when using instances of C extension types with a non-NULL tp_del slot.

禁用GC

只要能手动解决循环引用,就可以禁止GC模块来提高效率,因为GC适用于循环引用的垃圾回收机制。 如果可以确定代码没有循环引用,那么可以禁用GC模块

特殊说明(PEP442)

python3.4开始已经可以自动处理带有__del__方法的循环引用,也不会发生内存泄露了

import gc


class Foo(object):
    def __init__(self):
        self.bar = None
        print('foo init')

    def __del__(self):
        print("foo del")


class Bar(object):
    def __init__(self):
        self.foo = None
        print('bar init')

    def __del__(self):
        print('bar del')


def collect_and_show_garbage():
    print("Collecting...")
    n = gc.collect()
    print("unreachable objects:", n)
    print(gc.garbage)


def func():
    foo = Foo()
    bar = Bar()
    foo.bar = bar
    bar.foo = foo

# gc.set_debug(gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE)
func()
collect_and_show_garbage()

python2.7
foo init
bar init
Collecting…
(‘unreachable objects:’, 4)
[<main.Foo object at 0x101235550>, <main.Bar object at 0x1012355d0>]

python3.6
foo init
bar init
Collecting…
foo del
bar del
unreachable objects: 4
[]

gc.collect() 返回unreachable的数目,所以无论2.7还是3.6都一样,但、3.6中可以处理循环引用且带有__del__的情况,所以gc.garbage为空,当然如果没有__del__方法,2.7中gc.garbage也是空

爬虫(Web Crawler)是一种自动化程序,用于从互联网上收集信息。其主要功能是访问网页、提取数据并存储,以便后续分析或展示。爬虫通常由搜索引擎、数据挖掘工具、监测系统等应用于网络数据抓取的场景。爬虫的工作流程包括以下几个关键步骤:URL收集: 爬虫从一个或多个初始URL开始,递归或迭代地发现新的URL,构建一个URL队列。这些URL可以通过链接分析、站点地图、搜索引擎等方式获取。请求网页: 爬虫使用HTTP或其他协议向目标URL发起请求,获取网页的HTML内容。这通常通过HTTP请求库实现,如Python中的Requests库。解析内容: 爬虫对获取的HTML进行解析,提取有用的信息。常用的解析工具有正则表达式、XPath、Beautiful Soup等。这些工具帮助爬虫定位和提取目标数据,如文本、图片、链接等。数据存储: 爬虫将提取的数据存储到数据库、文件或其他存储介质中,以备后续分析或展示。常用的存储形式包括关系型数据库、NoSQL数据库、JSON文件等。遵守规则: 为避免对网站造成过大负担或触发反爬虫机制,爬虫需要遵守网站的robots.txt协议,限制访问频率和深度,并模拟人类访问行为,如设置User-Agent。反爬虫应对: 由于爬虫的存在,一些网站采取了反爬虫措施,如验证码、IP封锁等。爬虫工程师需要设计相应的策略来应对这些挑战。爬虫在各个领域都有广泛的应用,包括搜索引擎索引、数据挖掘、价格监测、新闻聚合等。然而,使用爬虫需要遵守法律和伦理规范,尊重网站的使用政策,并确保对被访问网站的服务器负责。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值