91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

在python項目中哪些情況下會出現內存泄漏

發布時間:2020-11-20 14:43:51 來源:億速云 閱讀:242 作者:Leah 欄目:開發技術

本篇文章為大家展示了在python項目中哪些情況下會出現內存泄漏,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

無窮大導致內存泄漏

如果把內存泄漏定義成只申請不釋放,那么借著 Python 中整數可以無窮大的這個特點,我們一行代碼就可以完成內存泄漏了。

i = 1024 ** 1024 ** 1024

循環引用導致內存泄漏

引用記數器 是 Python 垃圾回收機制的基礎,如果一個對象的引用數量不為 0 那么是不會被垃圾回收的,我們可以通過 sys.getrefcount 來得到給定對象的引用數量。

In [1]: import sys                               

In [2]: a = {'name':'tom','age':16}                       

In [3]: sys.getrefcount(a)  # 由于 getrefcount 內部也會臨時的引用 a 所以,使得計數器的值變成了 2 。               
Out[3]: 2

In [4]: b = a                                  

In [5]: sys.getrefcount(a)                           
Out[5]: 3

先來看一個循環引用的場景。

#!/usr/bin/evn python3

import sys
import time
import threading


class 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 了,現在釋放它的內存空間。")
    sys.stderr.flush()
    self.free_lock.release()


def mem_leak():
  """
  循環引用導致內存泄漏
  """
  zhang_san = Person(name='張三')
  li_si = Person("李四")

  # 構造出循環引用
  # 李四的好友是張三
  li_si.best_friend = zhang_san
  # 張三的好友是李四
  zhang_san.best_friend = li_si


if __name__ == "__main__":
  for i in range(3):
    time.sleep(0.01)
    print(f"{i}")
    mem_leak()

  print("mem_leak 執行完成了.")
  time.sleep(5)

運行效果。

python3 main.py
0
1
2
mem_leak 執行完成了.
張三 要 GG 了,現在釋放它的內存空間。
李四 要 GG 了,現在釋放它的內存空間。
張三 要 GG 了,現在釋放它的內存空間。
李四 要 GG 了,現在釋放它的內存空間。
張三 要 GG 了,現在釋放它的內存空間。
李四 要 GG 了,現在釋放它的內存空間

由于循環引用的存在,使得 mem_leak 函數就行執行完了其內部的局部變量引用計數器也不為 0 ,所以內存得不到及時的釋放。釋放這部分內存有兩個途徑 1、 被 Python 內部的循環檢測機制發現了; 2、進程退出前的集中釋放。

tracemalloc 可以在一定程序上幫我們發現問題,在此就不講怎么用了,我們直接上解決方案。Python 為程序員提供了弱引用,通過這種方式可以不增加對象引用計數器的數值,這成為了我們打破循環引用的一種手段。

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]: 2

In [6]: p = weakref.ref(tom)                          

In [7]: sys.getrefcount(tom)  # 弱引用不會增加計數器的值                        
Out[7]: 2

現在使用 weakref 技術來改造我們的代碼。

#!/usr/bin/evn python3


import sys
import time
import weakref
import threading


class 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 了,現在釋放它的內存空間。")
    sys.stderr.flush()
    self.free_lock.release()


def mem_leak():
  """
  循環引用導致內存泄漏
  """
  zhang_san = Person(name='張三')
  li_si = Person("李四")

  # 構造出循環引用
  # 李四的好友是張三
  li_si.best_friend = zhang_san
  # 張三的好友是李四
  zhang_san.best_friend = li_si


if __name__ == "__main__":
  for i in range(3):
    time.sleep(0.01)
    print(f"{i}")
    mem_leak()

  print("mem_leak 執行完成了.")
  time.sleep(5)

運行效果。

python3 main.py
0
張三 要 GG 了,現在釋放它的內存空間。
李四 要 GG 了,現在釋放它的內存空間。
1
張三 要 GG 了,現在釋放它的內存空間。
李四 要 GG 了,現在釋放它的內存空間。
2
張三 要 GG 了,現在釋放它的內存空間。
李四 要 GG 了,現在釋放它的內存空間。
mem_leak 執行完成了.

可以看到現在一旦函數執行完成,其內部的局部變量的內存就會得到釋放,非常的及時。

外面庫導致內存泄漏

這種情況我也只遇到過一次,之前 mysql-connector-python 的內存泄漏,導致我的程序跑著跑著占用的內存就越來越大;最后我們返的 C 語言擴展禁用之后就沒有問題了。

上述內容就是在python項目中哪些情況下會出現內存泄漏,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

同仁县| 昌吉市| 禹州市| 永平县| 东至县| 平乐县| 乌海市| 营口市| 枣阳市| 开封县| 阜南县| 青田县| 花莲县| 岐山县| 清新县| 茶陵县| 镇平县| 泰来县| 普定县| 江西省| 永年县| 襄樊市| 乌苏市| 泰和县| 平塘县| 永泰县| 郓城县| 墨脱县| 锡林浩特市| 尚志市| 赣州市| 公安县| 永仁县| 贵港市| 江北区| 东乡族自治县| 光山县| 东源县| 安乡县| 明光市| 枣强县|