Python 的内存管理机制

Python 的内存管理机制,第1张

Python采用自动内存管理,即Python会自动进行垃圾回收,不需要像C、C++语言一样需要程序员手动释放内存,手动释放可以做到实时性,但是存在内存泄露、空指针等风险。

Python自动垃圾回收也有自己的优点和缺点:优点:

缺点:

Python的垃圾回收机制采用 以引用计数法为主,分代回收为辅 的策略。

先聊引用计数法,Python中每个对象都有一个核心的结构体,如下

一个对象被创建时,引用计数值为1,当一个变量引用一个对象时,该对象的引用计数ob_refcnt就加一,当一个变量不再引用一个对象时,该对象的引用计数ob_refcnt就减一,Python判断是否回收一个对象,会将该对象的引用计数值ob_refcnt减一判断结果是否等于0,如果等于0就回收,如果不等于0就不回收,如下:

一个对象在以下三种情况下引用计数会增加:

一个对象在以下三种情况引用计数会减少:

验证案例:

运行结果:

事实上,关于垃圾回收的测试,最好在终端环境下测试,比如整数257,它在PyCharm中用下面的测试代码打印出来的结果是4,而如果在终端环境下打印出来的结果是2。这是因为终端代表的是原始的Python环境,而PyCharm等IDE做了一些特殊处理,在Python原始环境中,整数缓存的范围是在 [-5, 256] 的双闭合区间内,而PyCharm做了特殊处理之后,PyCharm整数缓存的范围变成了 [-5, 无穷大],但我们必须以终端的测试结果为主,因为它代表的是原始的Python环境,并且代码最终也都是要发布到终端运行的。

好,那么回到终端,我们来看两种特殊情况

前面学习过了,整数缓存的范围是在 [-5, 256] 之间,这些整数对象在程序加载完全就已经驻留在内存之中,并且直到程序结束退出才会释放占有的内存,测试案例如下:

如果字符串的内容只由字母、数字、下划线构成,那么它只会创建一个对象驻留在内存中,否则,每创建一次都是一个新的对象。

引用计数法有缺陷,它无法解决循环引用问题,即A对象引用了B对象,B对象又引用了A对象,这种情况下,A、B两个对象都无法通过引用计数法来进行回收,有一种解决方法是程序运行结束退出时进行回收,代码如下:

前面讲过,Python垃圾回收机制的策略是 以引用计数法为主,以分代回收为辅 。分代回收就是为了解决循环引用问题的。

Python采用分代来管理对象的生命周期:第0代、第1代、第2代,当一个对象被创建时,会被分配到第一代,默认情况下,当第0代的对象达到700个时,就会对处于第0代的对象进行检测和回收,将存在循环引用的对象释放内存,经过垃圾回收后,第0代中存活的对象会被分配为第1代,同样,当第1代的对象个数达到10个时,也会对第1代的对象进行检测和回收,将存在循环引用的对象释放内存,经过垃圾回收后,第1代中存活的对象会被分配为第2代,同样,当第二代的对象个数达到10个时,也会对第2代的对象进行检测和回收,将存在循环引用的对象释放内存。Python就是通过这样一种策略来解决对象之间的循环引用问题的。

测试案例:

运行结果:

如上面的运行结果,当第一代中对象的个数达到699个即将突破临界值700时(在打印699之前就已经回收了,所以看不到698和699)进行了垃圾回收,回收掉了循环引用的对象。

第一代、第二代、第三代分代回收都是有临界值的,这个临界值可以通过调用 gcget_threshold 方法查看,如下:

当然,如果对默认临界值不满意,也可以调用 gcset_threshold 方法来自定义临界值,如下:

最后,简单列出两个gc的其它方法,了解一下,但禁止在程序代码中使用

以上就是对Python垃圾回收的简单介绍,当然,深入研究肯定不止这些内容,目前,了解到这个程度也足够了。

使用 sysgetsizeof 方法可以查看 python 对象的内存占用,单位:字节 (byte)

实际上是调用了 __sizeof__ 方法:

有些数据类型在 Python3 和 Python2 中占用的内存是不同的,例如 range :

关于这个值是怎么算出来的,有待研究~

暂时已知:这个值包括该对象的数值、签名(包括数据类型、参数、调用方式等)等一系列数据所占总内存。可变对象所占内存可能极小,因为对象是指针,指向很大的数据。

Python导数据的时候,需要在一个大表上读取很大的结果集。

如果用传统的方法,Python的内存会爆掉,传统的读取方式默认在内存里缓存下所有行然后再处理,内存容易溢出

如果需要干别的,请另外再生成一个连接对象。

你好,

1、读取windows窗口,应该要用系统编程的知识实现接口,然后python调用

python 没有直接能实现该功能的模块

2、或者,你需要调用win32 api了已经不是python的标准范围

你可以看看 Pywin32 这个扩展库

1 使用装饰器来衡量函数执行时间

有一个简单方法,那就是定义一个装饰器来测量函数的执行时间,并输出结果:

import time

from functoolsimport wraps

import random

def fn_timer(function):

  @wraps(function)

  def function_timer(args, kwargs):

      t0= timetime()

      result= function(args, kwargs)

      t1= timetime()

      print("Total time running %s: %s seconds" %

          (function__name__, str(t1- t0))

)

      return result

return function_timer

@fn_timer

def random_sort(n):

  return sorted([randomrandom() for i in range(n)])

if __name__== "__main__":

  random_sort(2000000)

输出:Total time running random_sort: 06598007678985596 seconds

使用方式的话,就是在要监控的函数定义上面加上 @fn_timer 就行了

或者

# 可监控程序运行时间

import time

import random

def clock(func):

    def wrapper(args, kwargs):

        start_time= timetime()

        result= func(args, kwargs)

        end_time= timetime()

        print("共耗时: %s秒" % round(end_time- start_time, 5))

        return result

return wrapper

@clock

def random_sort(n):

  return sorted([randomrandom() for i in range(n)])

if __name__== "__main__":

  random_sort(2000000)

输出结果:共耗时: 065634秒

2 使用timeit模块

另一种方法是使用timeit模块,用来计算平均时间消耗。

执行下面的脚本可以运行该模块。

这里的timing_functions是Python脚本文件名称。

在输出的末尾,可以看到以下结果:4 loops, best of 5: 208 sec per loop

这表示测试了4次,平均每次测试重复5次,最好的测试结果是208秒。

如果不指定测试或重复次数,默认值为10次测试,每次重复5次。

3 使用Unix系统中的time命令

然而,装饰器和timeit都是基于Python的。在外部环境测试Python时,unix time实用工具就非常有用。

运行time实用工具:

输出结果为:

Total time running random_sort: 13931210041 seconds

real 149

user 140

sys 008

第一行来自预定义的装饰器,其他三行为:

    real表示的是执行脚本的总时间

    user表示的是执行脚本消耗的CPU时间。

    sys表示的是执行内核函数消耗的时间。

注意:根据维基百科的定义,内核是一个计算机程序,用来管理软件的输入输出,并将其翻译成CPU和其他计算机中的电子设备能够执行的数据处理指令。

因此,Real执行时间和User+Sys执行时间的差就是消耗在输入/输出和系统执行其他任务时消耗的时间。

4 使用cProfile模块

5 使用line_profiler模块

6 使用memory_profiler模块

7 使用guppy包

可以帮写。私信, 前提是

python版本用34~36

windows目标程序用windows自带的程序,比如notepad,计算器等

可以发给你运行测试,但发给你的是编译后的python字节码,不是代码本身

三方库用python官网的库,包括但不限于pywinauto

以上就是关于Python 的内存管理机制全部的内容,包括:Python 的内存管理机制、使用 sys.getsizeof 查看 python 对象的内存占用、解决python读取几千万行的大表内存问题等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9746311.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-01
下一篇2023-05-01

发表评论

登录后才能评论

评论列表(0条)

    保存