Python实现内存泄露排查的示例详解

作者:Sir?老王 时间:2021-03-03 21:55:29 

一般情况下只有需要长期运行的项目才会去关注内存的增长情况,即使是很小部分的内存泄露经过长期的运行仍然会产生很大的隐患。

python本身也是支持垃圾的自动回收的,但是在特定的情况下也是会出现内存泄露的问题的。

比如对于很多全局的列表(list)/字典(dict)等对象在经过不断的数据赋值而没有进行手动回收,或者某些对象被不停的循环引用而不能及时的进行回收等都会产生内存泄露的情况。

一般在python代码块的调试过程中会使用memory-profiler、filprofiler、objgraph等三种方式进行辅助分析,今天这里主要介绍使用objgraph对象提供的函数接口来进行内存泄露的分析。

objgraph是python的非标准模块,因此需要使用pip的方式安装一下。

pip install objgraph

更多详细的介绍可以访问下面的官方地址进行查看。

https://mg.pov.lt/objgraph/

接下来就可以直接将objgraph导入到我们的代码块中进行使用了。

# Importing the objgraph module and renaming it to graph.
import objgraph as graph

这里初始化一组字典类型的数据对象。

dict_ = {
    '姓名': ['Python', 'Java', 'Scala'],
    '年龄': ['21', '22', '19']
}

通过objgraph.count()函数,可以统计出GC中的dict_对象的数目是多少。

# Counting the number of dict_ objects in the GC.
print(graph.count(dict_))

和objgraph.count()函数对应的是可以使用by_type返回该对象在GC中的列表,若是GC返回的为空的列表说明已经被回收了。

# Returning a list of dict_ objects in the GC.
print(graph.by_type(dict_))

在统计内存泄露时比较好用的函数就是graph.show_growth()函数,可以统计自上次调用以来增加得最多的对象。

# Showing the growth of objects in the memory since the last time it was called.
print(graph.show_growth())

# function                       3013     +3013
# tuple                          1463     +1463
# dict                           1417     +1417
# wrapper_descriptor             1178     +1178
# ReferenceType                   883      +883
# method_descriptor               814      +814
# builtin_function_or_method      794      +794
# getset_descriptor               514      +514
# type                            463      +463
# list                            436      +436
# None

可以根据返回结果中的对象每次增加的数量来判断内存泄露的相关情况。

还有一个比较常用的分析函数就是graph.show_most_common_types(),可以按照从大到小的方式列出对象实例比较多的情况。

# Showing the most common types of objects in the memory.
print(graph.show_most_common_types())

# function                   3013
# tuple                      1463
# dict                       1417
# wrapper_descriptor         1178
# ReferenceType              883
# method_descriptor          814
# builtin_function_or_method 794
# getset_descriptor          514
# type                       463
# list                       436
# None

最后一个比较使用函数就是show_backrefs函数,使用它可以分析出内存泄露的原因是什么。

它会生成一张有关objs的引用图,可以看出对象为什么不释放?只是调用该函数时的参数比较多,下面是该函数的接口。

# def show_backrefs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10,
#                   highlight=None, filename=None, extra_info=None,
#                   refcounts=False, shortnames=True, output=None,
#                   extra_node_attrs=None):

我们还是和上面一样使用dict_作为对象进行分析。

# Showing the back references of the dict_ object.
graph.show_backrefs(dict_)

执行完成后dot类型的图片已经生成了,发现出现了下面的错误,意思是没有发现支持dot的图像组件。

# Graph written to C:\Users\86159\AppData\Local\Temp\objgraph-dkqm85f0.dot (4 nodes)
# Graph viewer (xdot) and image renderer (dot) not found, not doing anything else

可以使用pip的方式分别安装graphviz xdot,这两个python的非标准模块。

pip install graphviz xdot

若是查看.dot决策树图像可以使用graphviz工具,可以到下面地址进行下载安装。

https://graphviz.org/download/

安装完成后配置环境变量,然后重启开发工具(这里使用的是pycharm)即可。

来源:https://mp.weixin.qq.com/s/BVu4q7cZthuaxnOdsmhk0w

标签:Python,内存,泄露
0
投稿

猜你喜欢

  • Windows7 64位安装最新版本MySQL服务器的图文教程

    2024-01-28 18:39:24
  • 在Python中通过threshold创建mask方式

    2022-10-22 16:52:49
  • Python的垃圾回收机制详解

    2023-06-03 16:03:24
  • 使用eval()解析JSON格式字符串应注意的问题

    2008-04-16 15:46:00
  • 浅谈Scrapy框架普通反爬虫机制的应对策略

    2023-07-14 17:11:40
  • 关于vue.js中实现方法内某些代码延时执行

    2024-05-21 10:30:46
  • jRaiser与jQuery的冲突问题

    2010-07-27 12:36:00
  • 利用Python进行图像的加法,图像混合(附代码)

    2021-06-22 20:28:44
  • Go 处理大数组使用 for range 和 for 循环的区别

    2024-04-28 09:18:59
  • 使用matplotlib绘制图例标签中带有公式的图

    2022-07-19 00:40:48
  • PHP PDOStatement::getAttribute讲解

    2023-06-05 07:29:31
  • Pandas中把dataframe转成array的方法

    2023-07-05 11:44:34
  • Python PyPDF2模块安装使用解析

    2023-02-27 15:13:52
  • 动态给表添加删除字段并同时修改它的插入更新存储过程

    2024-01-17 22:12:56
  • Python selenium模块实现定位过程解析

    2021-01-10 10:50:27
  • MySQL中导出用户权限设置的脚本分享

    2024-01-21 15:29:04
  • python 获取毫秒级时间问题的解决

    2022-01-06 15:27:30
  • 通过Python pyecharts输出保存图片代码实例

    2021-09-14 22:26:11
  • FF和IE之间7个JavaScript的差异[译]

    2009-05-04 18:19:00
  • 怎样取得局域网中所有SQL Server的实例

    2009-01-08 13:20:00
  • asp之家 网络编程 m.aspxhome.com