为何要撰写这篇文章?
前段时间测试虚拟机用着用着就宕机了,然后我登录终端就弹出oom的错误,并且kill掉了一个python的程序,故我接着我以前的经验就说是不是内存泄漏了?哎!就是我说了下是不是内存泄漏,然后问题来了。我们的开发同学说“python内存泄漏?” 这下可好,那我就来分析一下Python到底会不会内存溢出。
什么叫内存泄漏?
内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。(摘:内存泄漏)
演示Python的内存泄漏
你可以说Python的内存管理是由“Python 内存管理器”来完成的,我们用户是不需要关心内存管理的,是的,你说的完全正确!虽然Python程序不可能像C/C++一样那样“忘记释放”内存没有free这样的Memory Leak,但是也会遇到“逻辑上Memory Leak”的情况。
def foo(a=[]):
a.append(time.time())
return a
例如一个未处理的回溯对象,它使整个堆栈帧保持活动状态,即使该函数不再运行,将值存储在类或全局范围而不是实例范围中,并且没有意识到这一点。类中的循环引用也有一个del方法。但是具有讽刺意味的是,del的存在使得循环垃圾收集器无法清理实例。
通过对比发现,内存确实在不断的变大。
#!/bin/python3
# encoding: utf-8import psutil, osdef memory_usage_psutil():
# 用来返回内存大小,单位MB
process = psutil.Process(os.getpid())
mem = process.memory_info()[0] / float(2 ** 20)
return memdef get_current_obj(a=[]):
a.append([0] * 1000)
return adef sum(a):
return a ** 2def main():
obj = []
for i in range(10000):
obj = get_current_obj(obj)
# 正常逻辑,我们每次调用get_current_obj完成后
# 内存都会释放,但是现实好想不是这样,内存而是
# 一直在增加。
if (i % 100 == 0):
print(memory_usage_psutil())
print("========Below is the sum function call.========")
for j in range(10000):
sum(j)
if (j % 100 == 0):
print(memory_usage_psutil())if __name__ == '__main__':
main()
以下是运行结果。
文章图片
可想而知,如果该程序是一直处理请求的后台程序,那您的服务器内存一定会被撑破的。
总结 最后Python到底有没有内存泄漏?答案是肯定的,但是不是与您所想的C代码“忘记回收内存”而导致的内存泄漏,而是在程序的运行中“进程占用的内存莫名其妙一直再升高”。进程占用内存一直升高,与逻辑预期不一致,最后导致了内存泄漏。
参考文献 python内存管理
memory-leak-in-python-requests
示例代码:
import requests
import gcdef call():# call the get with a url,here I used google.com
# get method returns a response object
response = requests.get('https://google.com')# print the status code of response
print("Status code",response.status_code)# After the function is been returned,
# the response object becomes non-referenced
returndef main():
print("No.of tracked objects before calling get method")# gc.get_objects() returns list objects been tracked
# by the collector.
# print the length of object list with len function.
print(len( gc.get_objects() ) )# make a call to the function, that calls get method.
call()# collect method immediately free the resource of
# non-referenced object.
gc.collect()# print the length of object list with len
# function after removing non-referenced object.
print("No.of tracked objects after removing non-referenced objects")
print(len( gc.get_objects() ) )if __name__ == "__main__":
main()
【Python程序到底有没有Memory Leak】Python 官方模块OS内存泄漏
Note On some platforms, including FreeBSD and macOS, setting environ may cause memory leaks. Refer to the system documentation for putenv().
Python memory leak
推荐阅读
- 推荐系统论文进阶|CTR预估 论文精读(十一)--Deep Interest Evolution Network(DIEN)
- Python专栏|数据分析的常规流程
- Python|Win10下 Python开发环境搭建(PyCharm + Anaconda) && 环境变量配置 && 常用工具安装配置
- Python绘制小红花
- Pytorch学习|sklearn-SVM 模型保存、交叉验证与网格搜索
- OpenCV|OpenCV-Python实战(18)——深度学习简介与入门示例
- python|8. 文件系统——文件的删除、移动、复制过程以及链接文件
- 爬虫|若想拿下爬虫大单,怎能不会逆向爬虫,价值过万的逆向爬虫教程限时分享
- 分布式|《Python3网络爬虫开发实战(第二版)》内容介绍
- java|微软认真聆听了开源 .NET 开发社区的炮轰( 通过CLI 支持 Hot Reload 功能)