python3 urllib 内存泄露_【专家专栏】张昊 | 从urllib2的内存泄露看python的GC
原標題:【專家專欄】張昊 | 從urllib2的內存泄露看python的GC
慘案回顧
領導:小張啊,安排你個任務,團隊需要你做一個功能,提取一批頁面上的數據,有問題嗎?
小張:當然沒問題,您啥時候要?
領導:明天上午給我行嗎?
小張:沒問題,我今天寫完跑一晚上就可以了。
天不遂人愿,小張第二天上班一看數據才提取了10%,再一看進程也不存在了且沒有報錯。
小張急急忙忙去找組內技術大拿老王求救。
小張:老王,我昨天在服務器上跑了一個腳本,現在進程不存在了也沒有報錯,這是咋回事?
老王:來我們看下dmesg,你看你的進程被kill掉了啊,估計是內存泄露,你用啥寫的腳本?
小張:用python啊,python還會內存泄露嗎?
老王:年輕人你用了urllib2了吧,你知道什么是GC么?
小張:emmmm.........
老王講課時間 python的GC
GC又名Garbage Collection,常用的垃圾回收算法有這幾種引用計數(Reference Count)、Mark-Sweep、Copying、分代收集。python使用的垃圾回收算法是引用計數,我們都知道一個python對象A賦值給另一個python對象B的時候,并不是開辟一塊新的存儲空間,而只是創造了新引用,每個對象都有存有指向該對象的引用總數,隨著使用對象越來越多,它們占用的內存就會越來越多,但是當有些對象沒用的時候,python自己的gc機制就會將這些沒用的對象清除釋放內存空間。python系統提供了sys.getrefcount()來查看一個變量的引用,通過下邊的例子我們可以初步了解python變量引用。
首先當使用某個引用作為參數,傳遞給getrefcount()時,參數實際上創建了一個臨時的引用,所以第一個輸出是2。將b賦值給a后,a的引用變成3,所以第二個輸出是3,同理可知第三個輸出是5。
從python的原理上來看當python的某個對象引用計數將為0時,說明沒有任何引用指向該對象,該對象就成為要被回收的垃圾了。比如某個新建對象,它被分配給某個引用,對象的引用計數變為1。如果引用被刪除,對象的引用計數為0,那么該對象就可以被垃圾回收。
gc庫
Python提供了gc庫來輔助開發者定位處理開發過程中遇到的GC的問題,常用的函數如下:
一般情況下我們可以通過使用gc.garbage來判斷是否存在內存泄露。
GC不是萬能的
我們來看下下邊這段代碼,使用gc.set_debug(gc.DEBUG_LEAK)來開啟內存泄露檢查,通過gc.collect()顯視的調用python的GC,通過遍歷gc.garbage來判斷是否存在內存泄露。
運行結果是:
這里會發現上述代碼是存在內存泄露,造成的原因就是lz與ow這兩個變量存在循環引用,Python 不知道按照什么樣的安全次序來調用對象的 __del__()函數,導致對象始終存活在 gc.garbage中,造成內存泄漏。
所以如果解決內存泄露只需要解開循環引用即可
老王破案時間
回過頭來看urllib2的問題,查看下urllib2.py的源碼
這里循環引用了HttpResponse(r)這個對象從而導致了內存泄露。
按照我們之前的思路只需要解除掉循環引用即可。
后續
小張:哇,原來還有這么多知識在里面,老王你不愧是組內一枝花,遇見人人夸。社會社會~
老王:出來混江湖的,沒有點墨水怎么吸引隔壁技術小妹妹~
小張:emmmmm........
作者介紹
張昊
(百度MTC研發&測試工程師)
自動化測試路漫漫,
吾輩吾輩砥礪前行。返回搜狐,查看更多
責任編輯:
總結
以上是生活随笔為你收集整理的python3 urllib 内存泄露_【专家专栏】张昊 | 从urllib2的内存泄露看python的GC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 张昊轩百天
- 下一篇: 分布式机器学习_229页CMU博士张昊毕