python内存泄漏

python基本运行机制。Python程序运行时不需要编译成二进制代码,而直接从源码运行程序,简单来说是,Python解释器将源码转换为字节码,然后再由解释器来执行这些字节码。

解释器的具体工作:

1 完成模块的加载和链接;

2 将源代码编译为PyCodeObject对象(即字节码),写入内存中,供CPU读取;

3 从内存中读取并执行,结束后将PyCodeObject写回硬盘当中,也就是复制到.pyc或.pyo文件中,以保存当前目录下所有脚本的字节码文件;

* 之后若再次执行该脚本,它先检查【本地是否有上述字节码文件】和【该字节码文件的修改时间是否与其脚本一致】。是就直接执行,否则重复上述步骤。

 

如果你的程序是死循环,不停歇的代码,下列是需要注意内存的问题。
第一、pillow库的隐患

#内存将发生泄漏
from PIL import  Image

im = Image.open('1.jpg')
im.save()

#使用with使程序更安全
from PIL import  Image

with open('1.jpg' , 'rb') as open_file:
    im = Image.open(open_file)

第二、使用importlib.reload重载模块后带来使用全局变量带来的隐患
假如采取不重启程序方式,自动重新载入修改后的文件,所以需要进行重载模块

#run.py
import importlib

while True:
    module_name = importlib.import_module('.', 'test_file')
    module_name = importlib.reload(module_name)
    result = module_name.main(params)

#test_file.py
global_value = {'dataList':[],
                'number':'',}
key = '初始值'

def main(params):

    # params携带着此次任务数据

    global_value['number'] = params['number']
    get_data1(params)
    get_data2(params)
    return global_value

def get_data1(params):
    global key
    # 你的程序通过params得到新的数据
    data_once = {'每次运行产生的键': '每次运行产生的键值'}
    key = '新值'
    global_value['dataList'].append(data_once)

def get_data2(params):
    # 你的程序通过params和key新的值,得到另一份数据
    data_once = {'每次运行产生的新键': '每次运行产生的新键值'}
    global_value['dataList'].append(data_once)

上述就会发生一种隐患,以前我觉得垃圾回收机制很靠谱。但是当每一次重载模块时,global_value将使用新的地址,原来的地址还放着上一次的数据,没有被释放掉
就算你在每次循环里添加gc.collect()也不能快速回收删除上一次的数据,导致内存持续增长。。。


我的处理方式是
(1)将global_value这个转移进函数内,通过传参将get_data1和get_data2数据整合在一个变量里
(2)将所有函数放在一个类中,也可以避免全局变量数据存活时间太长


总结,虽然使用全局变量很省事,不用传参,其他函数改变其值再被其他函数调用很方便,却会导致内存泄漏,因为每一次reload时产生的是新的内存地址。

转载于:https://www.cnblogs.com/7134g/p/11516818.html

Python内存泄露通常是指程序在运行过程中,分配的内存在不再需要的时候未被释放,导致可用内存逐渐减少,最终可能会导致程序运行缓慢甚至崩溃。Python有自动的垃圾回收机制,可以自动管理内存,但是在某些情况下,例如循环引用、不正确的类设计等,可能会导致内存泄露Python的垃圾回收主要依赖于引用计数和循环垃圾回收(Generational Garbage Collection)。引用计数机制可以跟踪对象的引用次数,当引用次数为零时,对象会被立即回收。循环垃圾回收则是用来处理循环引用的情况,它能够识别并清除相互引用形成的数据结构。 以下是一些可能导致Python内存泄露的原因和解决方法: 1. 循环引用:两个或更多的对象相互引用,导致它们的引用计数永远不为零,无法被回收。 2. 全局变量和闭包:长时间存在的全局变量或闭包可能会引用大量的数据,这可能会阻碍垃圾回收器回收这些数据。 3. C扩展:使用C语言编写的扩展模块如果没有正确管理内存,也可能导致内存泄露。 4. 缓存机制:如果缓存没有适当地限制大小,可能会不断积累数据,占用越来越多的内存。 为了防止内存泄露,应该注意以下几点: - 尽量避免不必要的全局变量,尤其是在大型应用中。 - 使用弱引用(weakref)来避免循环引用,当没有其他引用指向对象时,可以被垃圾回收器回收。 - 适时地删除不再使用的对象,尤其是大型数据结构。 - 监控内存使用情况,及时发现异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值