亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

總結(jié)python 三種常見(jiàn)的內(nèi)存泄漏場(chǎng)景

瀏覽:18日期:2022-07-04 17:40:37

概要

不要以為 Python 有自動(dòng)垃圾回收就不會(huì)內(nèi)存泄漏,本著它有“垃圾回收”我有“垃圾代碼”的精神,現(xiàn)在總結(jié)一下三種常見(jiàn)的內(nèi)存泄漏場(chǎng)景。

無(wú)窮大導(dǎo)致內(nèi)存泄漏

如果把內(nèi)存泄漏定義成只申請(qǐng)不釋放,那么借著 Python 中整數(shù)可以無(wú)窮大的這個(gè)特點(diǎn),我們一行代碼就可以完成內(nèi)存泄漏了。

i = 1024 ** 1024 ** 1024

循環(huán)引用導(dǎo)致內(nèi)存泄漏

引用記數(shù)器 是 Python 垃圾回收機(jī)制的基礎(chǔ),如果一個(gè)對(duì)象的引用數(shù)量不為 0 那么是不會(huì)被垃圾回收的,我們可以通過(guò) sys.getrefcount 來(lái)得到給定對(duì)象的引用數(shù)量。

In [1]: import sys In [2]: a = {’name’:’tom’,’age’:16} In [3]: sys.getrefcount(a) # 由于 getrefcount 內(nèi)部也會(huì)臨時(shí)的引用 a 所以,使得計(jì)數(shù)器的值變成了 2 。 Out[3]: 2In [4]: b = a In [5]: sys.getrefcount(a) Out[5]: 3

先來(lái)看一個(gè)循環(huán)引用的場(chǎng)景。

#!/usr/bin/evn python3import sysimport timeimport threadingclass Person(object): free_lock = threading.Condition() def __init__(self, name: str = ''): ''' Parameters ---------- name: str 姓名 best_friend: str 最要好的朋友名 ''' self._name = name self._best_friend = None @property def best_friend(self, person: 'Person'): return self._best_friend @best_friend.setter def best_friend(self, friend: 'Person'): self._best_friend = friend def __str__(self): ''' ''' return self._name def __del__(self): ''' ''' self.free_lock.acquire() print(f'{self._name} 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。') sys.stderr.flush() self.free_lock.release()def mem_leak(): ''' 循環(huán)引用導(dǎo)致內(nèi)存泄漏 ''' zhang_san = Person(name=’張三’) li_si = Person('李四') # 構(gòu)造出循環(huán)引用 # 李四的好友是張三 li_si.best_friend = zhang_san # 張三的好友是李四 zhang_san.best_friend = li_siif __name__ == '__main__': for i in range(3): time.sleep(0.01) print(f'{i}') mem_leak() print('mem_leak 執(zhí)行完成了.') time.sleep(5)

運(yùn)行效果。

python3 main.py 012mem_leak 執(zhí)行完成了.張三 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。李四 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。張三 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。李四 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。張三 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。李四 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間

由于循環(huán)引用的存在,使得 mem_leak 函數(shù)就行執(zhí)行完了其內(nèi)部的局部變量引用計(jì)數(shù)器也不為 0 ,所以內(nèi)存得不到及時(shí)的釋放。釋放這部分內(nèi)存有兩個(gè)途徑 1、 被 Python 內(nèi)部的循環(huán)檢測(cè)機(jī)制發(fā)現(xiàn)了; 2、進(jìn)程退出前的集中釋放。

tracemalloc 可以在一定程序上幫我們發(fā)現(xiàn)問(wèn)題,在此就不講怎么用了,我們直接上解決方案。Python 為程序員提供了弱引用,通過(guò)這種方式可以不增加對(duì)象引用計(jì)數(shù)器的數(shù)值,這成為了我們打破循環(huán)引用的一種手段。

In [1]: import sys In [2]: import weakref In [3]: from main import Person In [4]: tom = Person(’tom’) In [5]: sys.getrefcount(tom) Out[5]: 2In [6]: p = weakref.ref(tom) In [7]: sys.getrefcount(tom) # 弱引用不會(huì)增加計(jì)數(shù)器的值Out[7]: 2

現(xiàn)在使用 weakref 技術(shù)來(lái)改造我們的代碼。

#!/usr/bin/evn python3import sysimport timeimport weakrefimport threadingclass Person(object): free_lock = threading.Condition() def __init__(self, name: str = ''): ''' Parameters ---------- name: str 姓名 best_friend: str 最要好的朋友名 ''' self._name = name self._best_friend = None @property def best_friend(self, person: 'Person'): return self._best_friend @best_friend.setter def best_friend(self, friend: 'Person'): self._best_friend = weakref.ref(friend) def __str__(self): ''' ''' return self._name def __del__(self): ''' ''' self.free_lock.acquire() print(f'{self._name} 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。') sys.stderr.flush() self.free_lock.release()def mem_leak(): ''' 循環(huán)引用導(dǎo)致內(nèi)存泄漏 ''' zhang_san = Person(name=’張三’) li_si = Person('李四') # 構(gòu)造出循環(huán)引用 # 李四的好友是張三 li_si.best_friend = zhang_san # 張三的好友是李四 zhang_san.best_friend = li_siif __name__ == '__main__': for i in range(3): time.sleep(0.01) print(f'{i}') mem_leak() print('mem_leak 執(zhí)行完成了.') time.sleep(5)

運(yùn)行效果。

python3 main.py 0張三 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。李四 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。1張三 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。李四 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。2張三 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。李四 要 GG 了,現(xiàn)在釋放它的內(nèi)存空間。mem_leak 執(zhí)行完成了.

可以看到現(xiàn)在一旦函數(shù)執(zhí)行完成,其內(nèi)部的局部變量的內(nèi)存就會(huì)得到釋放,非常的及時(shí)。

外面庫(kù)導(dǎo)致內(nèi)存泄漏

這種情況我也只遇到過(guò)一次,之前 mysql-connector-python 的內(nèi)存泄漏,導(dǎo)致我的程序跑著跑著占用的內(nèi)存就越來(lái)越大;最后我們返的 C 語(yǔ)言擴(kuò)展禁用之后就沒(méi)有問(wèn)題了。

以上就是總結(jié)python 三種常見(jiàn)的內(nèi)存泄漏場(chǎng)景的詳細(xì)內(nèi)容,更多關(guān)于python 內(nèi)存泄漏的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 国产精品高清视亚洲精品 | 高中生福利视频在线观看 | 一级毛片一级毛片a毛片欧美 | 99久久这里只精品国产免费 | 亚洲欧美国产日产综合不卡 | 福利视频在线观看免费版 | 中文字幕在线视频播放 | 久久久久日韩精品免费观看网 | 男人的天堂久久精品激情 | 亚洲首页在线观看 | 好吊色青青青国产在线观看 | 日韩第二页 | 免费a级| 久久毛片| 在线va| 国产成人久久精品二区三区 | 色在线免费 | 成年性午夜免费视频网站不卡 | 免费国产视频 | 2048亚洲精品国产 | 欧美第二区 | 亚洲视频毛片 | 亚洲第一人黄所 | 午夜视频福利在线 | 黄色一区二区三区 | 国产亚洲精品看片在线观看 | 人人狠狠综合88综合久久 | 亚洲精品美女视频 | 日韩免费视频播放 | 午夜毛片不卡高清免费 | 天天色综合影视 | 亚洲精品国产第一区二区三区 | 亚洲欧美日韩中文综合在线不卡 | 手机看片国产高清 | 狠狠色丁香婷婷综合激情 | 99精品在线免费 | 国产精品亚洲w码日韩中文 国产精品亚洲成在人线 | 免费艹逼视频 | 人人草人人澡 | 国产国拍亚洲精品av | 久久九九免费 |