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
猜你喜欢
- ASP.net处理文件上传就简单的多了,我呢也是在学习中,顺便写写学习笔记。 先在表单中添加enctype="multipart/
- 本文实例讲述了python通过colorama模块在控制台输出彩色文字的方法。分享给大家供大家参考。具体分析如下:colorama是一个py
- 一、采用?a=1&b=2访问修改views.py:views.pyfrom django.shortcuts import rend
- 零基础学习Python的入手方向:1、首先你确定学习Python用来做什么方向,爬虫还是……;2、确定方向后,就按照你喜欢的方式找学习资料;
- <div id="outer" style="background:#099"> cli
- 上篇文章介绍了什么是进程、进程与程序的关系、进程的创建与使用、创建进程池等,接下来就来介绍一下进程同步及进程通信。进程同步当多个进程使用同一
- 可控制的滚动新闻不同于自动的滚动条,它是通过按钮控制移动的,当你把鼠标放在按钮上时,新闻内容就会向上或
- 本文实例讲述了Python中itertools模块用法,分享给大家供大家参考。具体分析如下:一般来说,itertools模块包含创建有效迭代
- 队列和优先队列(Priority Queue)队列是一种可以完成插入和删除的数据结构。普通队列是先进先出(FIFO), 即先插入的先被删除。
- 剑指Offer(Python多种思路实现):剪绳子面试14题:题目:剪绳子题:给你一根长度为n的绳子,请把绳子剪成m段(m,n都是整数,且n
- 先简单说一下MP3的ID3 标记,因为主要是操作这个玩意MP3最开始的时候没有我们今天看到的那样,有歌手、年代,专集等等信息只有一些简单的参
- 在对dataframe进行分析的时候会遇到需要分组计数,计数的column中属性有重复,但又需要仅对不重复的项计数(即重复N次出现的项只计1
- 最近看到市场上各种的文档格式转换软件,要么是收费、要么是有大量的广告。于是学习了一下 PyQt5 的页面操作,再加上了解 pandas 的使
- 使用Scrapy爬取豆瓣某影星的所有个人图片以莫妮卡·贝鲁奇为例1.首先我们在命令行进入到我们要创建的目录,输入 scrapy startp
- 本文实例讲述了django框架model orM使用字典作为参数,保存数据的方法。分享给大家供大家参考,具体如下:假设有一个字典,里面已经有
- 我就废话不多说啦,还是直接看代码吧!import osimport sysimport djangosys.path.append(r
- 作者的blog:http://www.planabc.netz-index属性简介引用:z-index : auto | numberaut
- 由于办公需要“每天定时推送某消息用来提醒群里面所有人”,有同事提议用企业微信自带的机器人来实现此功能。我觉得企业微信的这个工具还不错,具体使
- 最近一周每天早上起来第一件事,就是打开新闻软件看疫情相关的新闻。了解下自己和亲友所在城市的确诊人数,但纯数字还是缺乏一个直观的概念。那我们来
- 1、 利用操作符+比如:a = [1,2,3]b = [4,5,6]c = a+bc的结果:[1,2,3,4,5,6] 2 利用e