python外篇(内存泄露)

这篇具有很好参考价值的文章主要介绍了python外篇(内存泄露)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

了解

循环引用造成的内存泄露

大量创建对象造成的内存泄漏

全局对象造成的内存泄露

不适当缓存造成的内存泄露

内存分析工具 


了解

### 以下为Python中可能会出现内存泄露的情况:
    (1) 循环引用:当两个或多个对象相互引用,造成的循环引用进而导致内存泄露
    (2) 大量创建对象:当程序中频繁创建大量的对象并没有及时销毁,也会导致内存泄露。
    (3) 全局变量:当全局变量被创建后一直存在,即使它们不再被使用,也会占用内存空间,可能导致内存泄露。
    (4) 不适当的缓存使用:如果在缓存中存储了大量数据,而没有适当地删除旧数据,会导致内存泄漏。
    (5) C扩展模块:使用C扩展模块编写的代码可能会出现内存泄漏问题,因为C扩展代码不受Python的垃圾回收机制控制。


    

### 以下为避免这些情况导致的内存泄漏的措施:
    (1) 尽可能避免循环引用,使用weakref库避免对象之间相互引用。
    (2) 及时销毁不需要的对象,特别是大量创建的对象。
    (3) 减少全局变量的使用,只在必要时使用。
    (4) 注意缓存的使用,需要定期清理缓存,避免缓存数据过多导致内存泄漏。
    (5) 尽可能避免使用C扩展模块,如果必须使用,需要仔细检查代码,确保它没有导致内存泄漏问题。
    (6) 使用生成器和迭代器:生成器和迭代器是Python中用于处理大型数据集合的高效工具。它们可以逐个返回数据,而不是一次性返回整个数据集合。使用生成器和迭代器可以减少对内存的需求,避免内存泄漏。
    (7) 使用with语句:with语句是Python中用于管理资源的一种语法,它可以自动关闭文件和数据库连接等资源,避免资源未被正确释放导致的内存泄漏。
    (8) 使用内存分析工具:Python中有一些内存分析工具可以帮助我们检测和解决内存泄漏问题,例如pympler和memory_profiler等工具。使用这些工具可以定位内存泄漏的代码,并进行优化。

循环引用造成的内存泄露

### 介绍:    
    在python中,都知道当一个变量不被引用的时候(引用计数为0)就会触发垃圾回收机制从而被从内存中删除,但如果在两个对象间去互相引用(你引用我,我也引用你),这样就会形成一个无限循环引用(你引用我,我引用你,你又引用我,我又引用你...),那么此时两个对象一直处于被引用状态,意味着逃避了垃圾回收机制的回收,在内存中一直循环引用占用着内存资源,从而导致这些内存资源将不能被再次使用。这就是循环引用造成的内存泄露问题。
    
    
### 代码问题阐述:

class Person:
    def __init__(self, name):
        self.name = name
        self.cars = []

    def add_car(self, car):
        self.cars.append(car)
        car.owner = self


class Car:
    def __init__(self, kind):
        self.kind = kind
        self.owner = None


person = Person("Joden")
car = Car("Tesla")
person.add_car(car)
# car.owner = self
# self.cars = [car]

### 代码解决阐述:

(1) 以下为解决阐述:
    使用弱引用,弱引用不会增加一个变量或对象的引用计数
    
(2) 以下为解决代码阐述:

import weakref


class Person:
    def __init__(self, name):
        self.name = name
        self.cars = []

    def add_car(self, car):
        self.cars.append(weakref.ref(car))
        car.owner = weakref.ref(self)


class Car:
    def __init__(self, kind):
        self.kind = kind
        self.owner = None


person = Person("Joden")
car = Car("Tesla")
person.add_car(car)
# car.owner = weakref.ref(self)
# self.cars = [weakref.ref(car)]

大量创建对象造成的内存泄漏

### 介绍:
    当创建大量对象,并且不能及时被垃圾回收机制回收,从而导致的内存泄露问题
    
    
### 代码问题阐述:

class MyClass:
    def __init__(self, data):
        self.data = date


objs = []
for i in range(1000000):
    obj = MyClass(i)
    objs.append(obj)


    阐述:在这个示例中,我们构建了一个耗时的循环创建对象,并且不断将对象添加到列表中,这样在循环的过程中列表就无法被短时间内释放,就会在此期间一直占用内存,从而造成内存泄露问题
            
        
### 代码解决阐述:

class MyClass:
    def __init__(self, data):
        self.data = date


def create_objs(num):
    for i in range(num):
        obj = MyClass(i)
        yield obj


    阐述:在这个示例中,我们将创建对象过程放在了函数内并且用生成器来返回我们创建的对象,这样只有需要时才会去创建对象就避免了,大量创建对象造成的内存泄露问题

全局对象造成的内存泄露

### 介绍:
    在了解这个全局变量造成的内存泄露之前还需要了解两个知识:深拷贝和浅拷贝、全局变量。
    深拷贝和浅拷贝:在python中对基本数据类型的引用都是浅拷贝(实际上就是对内存id的引用,本质上为指向同一个内存地址的引用),而深拷贝就不一样了,比如对象、list、dict等等,它们被引用时就会开辟新的内存空间来存储这些数据。
    全局变量:很简单,创建一个py文件(模块),直接在py文件内定义的变量就是全局变量(而非在函数内等局部作用域中定义的变量)。
    那么,现在就很好理解全局变量造成的内存泄露问题了。当某些模块中的全局变量被程序中多次引用,那么每次引用就会重新开辟内存空间来存储,这样就会占用大量的内存空间从而造成内存泄露问题。
    对于如何解决这个问题,方案是单例模式,单例模式可以确保类在内存中只有一个实例然后在整个程序中都会对其引用,这样就避免了全局变量被多次在内存中创建从而导致的内存泄露问题。、

### 代码问题阐述:

my_list = [...]


    这个my_list在程序中被多次引用,而且倘若my_list占用较大空间

### 代码解决阐述:

class Singleton:
    __instance = None

    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = super().__new__(cls)
            cls.__instance.my_list = []
        return cls.__instance


def add_data(new_data):
    obj = Singleton()
    obj.my_list.append(new_data)


def get_data():
    obj = Singleton()
    return obj.my_list


add_data(1)
add_data(2)
add_data(3)
get_list = get_data()

不适当缓存造成的内存泄露

### 了解:
    对于这个“不适当的缓存造成的内存泄露”是我们使用缓存原理要注意的,如果我们的缓存中数据量过大时就有一定的风险了,如果这个缓存在短时间内没被清除且一直变大就会占用越来越多的内存就有可能造成内存泄露,而且如果程序运行过程中突然崩溃强制关闭,此时内存中的数据也可能无法清理总而造成内存泄露。
    那么,对于解决“不适当的缓存造成的内存泄露”问题呢?其实本质上也是由长时间引用没被释放造成的,所以可以使用弱引用来解决。

### 问题代码阐述:

class Calculator:
    __cache = {}

    @classmethod
    def add(cls, a, b):
        key = f"add_{a}_{b}"
        if key in cls.__cache:
            return cls.__cache[key]
        result = a + b
        cls.__cache[key] = result
        return result

    在这个示例中我们使用字典作为加法计算的缓存,如果已经计算过了就直接引用,否则将添加到缓存字典中,考虑假若它是我们python底层实现的“加法”,我们在一个大型项目程序中将会多少次调用它,所以如果不能及时释放缓存,缓存反而会弄巧成拙

### 解决代码阐述:

import weakref


class Calculator:
    __cache = weakref.WeakValueDictionary()

    @classmethod
    def add(cls, a, b):
        key = f"add_{a}_{b}"
        result = cls.__cache.get(key)
        if result is None:
            result = a + b
            cls.__cache[key] = result
        return result

内存分析工具 

### 工具介绍(需要自己去了解)  
    gc:python内置的内存分析模块
    objgraph:用于生成 Python 对象引用图,可以帮助我们找出引用计数不正确的对象。
    memory_profiler:用于逐行分析 Python 代码的内存使用情况,可以帮助我们找出内存占用过高的代码段。
    pympler:包含了多个子模块,可以帮助我们分析 Python 中的内存使用情况,包括对象分配、垃圾回收、内存泄露等。
    heapy:基于 Guppy,可以用于分析 Python 中的内存使用情况,包括内存分配情况、对象大小分布、内存泄露等。
    我们可以在程序中使用这些工具,来查看内存使用情况、对象数量等信息,以及跟踪内存泄露和内存占用过高的问题。具体使用方法可以参考对应工具的官方文档。文章来源地址https://www.toymoban.com/news/detail-407050.html

到了这里,关于python外篇(内存泄露)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一文了解Python中的while循环语句

    目录 🥩循环语句是什么 🥩while循环 🥩遍历猜数字 🥩while循环嵌套 🥩while循环嵌套案例      🦐博客主页:大虾好吃吗的博客      🦐专栏地址:Python从入门到精通专栏         循环语句在编程中非常有用,可以帮助我们重复执行特定的代码块,从而实现一些重复性

    2024年02月15日
    浏览(46)
  • 微信小程序的目录解析--【浅入深出系列001外篇】

    微信目录集链接在此: 详细解析黑马微信小程序视频–【思维导图知识范围】 难度★✰✰✰✰ 用免费公开视频,卷飞培训班哈人!打死不报班,赚钱靠狠干! 只要自己有电脑,前后项目都能搞!N年苦学无人问,一朝成名天下知! 黑马程序员微信小程序开发前端教程_零基础

    2024年02月17日
    浏览(47)
  • 什么是内存溢出?什么是内存泄露?

    文章目录 一、什么是内存溢出?  二、什么是内存泄露? 三、如何避免内存溢出和内存泄露? 一、什么是内存溢出?         假设我们JVM中可用的内存空间只有 3M ,但是我们要创建一个 5M 的对象,那么新创建的对象就放不进去了。这个时候,我们就叫做内存溢出。就好

    2024年02月08日
    浏览(67)
  • 内存溢出、内存泄露的概述及常见情形

    java doc 中对 Out Of Memory Error 的解释是,没有空闲内存,并且垃圾收集器也无法提供更多内存。 JVM 提供的内存管理机制和自动垃圾回收极大的解放了用户对于内存的管理,由于 GC(垃圾回收)一直在发展,所有一般情况下,除非应用程序占用的内存增长速度非常快,造成垃圾

    2024年01月21日
    浏览(49)
  • 【web渗透思路】框架敏感信息泄露(特点、目录、配置)

      博主:网络安全领域狂热爱好者(承诺在CSDN永久无偿分享文章)。 殊荣:CSDN网络安全领域优质创作者,2022年双十一业务安全保卫战-某厂第一名,某厂特邀数字业务安全研究员,edusrc高白帽,vulfocus、攻防世界等平台排名100+、高校漏洞证书、cnvd原创漏洞证书等。 擅长:对

    2023年04月19日
    浏览(44)
  • pytorch 训练过程内存泄露/显存泄露debug记录:dataloader和dataset导致的泄露

    微调 mask-rcnn 代码,用的是 torchvision.models.detection.maskrcnn_resnet50_fpn 代码,根据该代码的注释,输入应该是: images, targets=None (List[Tensor], Optional[List[Dict[str, Tensor]]]) - Tuple[Dict[str, Tensor], List[Dict[str, Tensor]]] 所以我写的 dataset 是这样的: 大概思路是: 先把所有的标注信息读入内存

    2024年02月14日
    浏览(50)
  • 【Android 性能优化:内存篇】——WebView 内存泄露治理

    背景:笔者在公司项目中优化内存泄露时发现WebView 相关的内存泄露问题非常经典,一个 Fragment 页面使用的 WebView 有多条泄露路径,故记录下。 项目中一个Fragment 使用 Webview,在 Fragment onDestroyView 时候却没有释放,释放 WebView 还不简单嘛,于是笔者在 Fragment 的 onDestroyView 补充

    2024年02月04日
    浏览(44)
  • go 内存泄露

    事件回顾 9.15号晚18点服务端发版 9.16号晚21点监控显示自发版后服务器 TCP_alloc 指标一路飙升至40K(如图) 问题分析 看到 tcp_alloc 指标异常,初步怀疑有tcp连接创建后未关闭,应该是上次发版写了什么代码导致的。回顾此次发版清单,问题应该出现在了daemon服务心跳上报上。 d

    2024年02月07日
    浏览(46)
  • Java 内存泄露问题详解

    目录 1、什么是内存泄露? 2、Java 中可能导致内存泄露的场景 3、长生命周期对象持有短生命周期对象引用造成的内存泄露问题示例 4、静态集合类持有对象引用造成内存泄露问题的示例 1、什么是内存泄露?         内存泄露指的是程序运行时未能正确释放不再使用的内

    2024年02月09日
    浏览(41)
  • C++内存泄露

    目录 1.什么是内存泄露 2.内存泄露的危害 3.如何解决内存泄露等相关的问题         在C/C++中 ,我们申请了资源,因为一些原因忘记对申请的资源进行释放,或者因为异常安全等问题没有进行释放就会造成内存泄露的。          一般来说,如果不是长期运行的程序,内存泄

    2024年02月09日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包