這篇文章將為大家詳細(xì)講解有關(guān)Python內(nèi)存泄漏和內(nèi)存溢出的解決方法,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
創(chuàng)新互聯(lián)是專業(yè)的茅箭網(wǎng)站建設(shè)公司,茅箭接單;提供網(wǎng)站建設(shè)、做網(wǎng)站,網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行茅箭網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!一、內(nèi)存泄漏
像Java程序一樣,雖然Python本身也有垃圾回收的功能,但是同樣也會(huì)產(chǎn)生內(nèi)存泄漏的問(wèn)題。
對(duì)于一個(gè)用 python 實(shí)現(xiàn)的,長(zhǎng)期運(yùn)行的后臺(tái)服務(wù)進(jìn)程來(lái)說(shuō),如果內(nèi)存持續(xù)增長(zhǎng),那么很可能是有了“內(nèi)存泄露”。
1、內(nèi)存泄露的原因
對(duì)于 python 這種支持垃圾回收的語(yǔ)言來(lái)說(shuō),怎么還會(huì)有內(nèi)存泄露? 概括來(lái)說(shuō),有以下三種原因:
為什么循環(huán)引用的對(duì)象定義了__del__方法后collect就不起作用了呢?
gc模塊最常使用的方法就是gc.collect()方法,使用collect方法對(duì)循環(huán)引用的對(duì)象進(jìn)行垃圾回收。
如果我們?cè)陬愔兄剌d了__del__方法。__del__方法定義了在用del語(yǔ)句刪除對(duì)象時(shí)除了釋放內(nèi)存空間以外的操作。
一般而言,在使用了del語(yǔ)句的時(shí)候解釋器首先會(huì)看要?jiǎng)h除對(duì)象的引用計(jì)數(shù),如果為0,那么就釋放內(nèi)存并執(zhí)行del方法。
在這里,首先del語(yǔ)句出現(xiàn)時(shí)本身引用計(jì)數(shù)就不為0(因?yàn)橛醒h(huán)引用的存在),所以解釋器不釋放內(nèi)存;
再者,執(zhí)行collect方法時(shí)應(yīng)該會(huì)清除循環(huán)引用所產(chǎn)生的無(wú)效引用計(jì)數(shù)從而達(dá)到del的目的,對(duì)于這兩個(gè)循環(huán)引用對(duì)象而言,
python無(wú)法判斷調(diào)用它們的del方法時(shí)會(huì)不會(huì)要用到對(duì)方那個(gè)對(duì)象,比如在進(jìn)行b.del()時(shí)可能會(huì)用到b._a也就是a,如果在那之前a已經(jīng)被釋放,那么就徹底GG了。
為了避免這種情況,collect方法默認(rèn)不對(duì)重載了del方法的循環(huán)引用對(duì)象進(jìn)行回收,而它們倆的狀態(tài)也會(huì)從unreachable轉(zhuǎn)變?yōu)閡ncollectable。由于是uncollectable的,自然就不會(huì)被collect處理,所以就進(jìn)入了garbage列表。
2、內(nèi)存泄露的診斷思路
無(wú)論是哪種方式的內(nèi)存泄露,最終表現(xiàn)的形式都是某些 python 對(duì)象在不停的增長(zhǎng);因此,首先是要找到這些異常的對(duì)象。
3、診斷步驟
用到的工具: gc 模塊和 objgraph 模塊
gc模塊 是Python的垃圾收集器模塊,gc使用標(biāo)記清除算法回收垃圾
objgraph 是一個(gè)用于診斷內(nèi)存問(wèn)題的工具
import gc import objgraph ### 強(qiáng)制進(jìn)行垃圾回收 gc.collect() ### 打印出對(duì)象數(shù)目最多的 50 個(gè)類型信息 objgraph.show_most_common_types(limit=50)