gc --- 垃圾回收器介面 (Garbage Collector interface)


此 module(模組)提供可選的垃圾回收器介面,提供的功能包括:關閉回收器、調整回收頻率、設定除錯選項。它同時提供對回收器有找到但是無法釋放的不可達物件 (unreachable object) 的存取。由於 Python 使用了帶有參照計數的回收器,如果你確定你的程式不會產生參照迴圈 (reference cycle),你可以關閉回收器。可以透過呼叫 gc.disable() 關閉自動垃圾回收。若要為一個存在記憶體流失的程式 (leaking program) 除錯,請呼叫 gc.set_debug(gc.DEBUG_LEAK);需要注意的是,它包含 gc.DEBUG_SAVEALL,使得被回收的物件會被存放在 gc.garbage 中以待檢查。

gc module 提供下列函式:

gc.enable()

啟用自動垃圾回收。

gc.disable()

停用自動垃圾回收。

gc.isenabled()

如果啟用了自動回收則回傳 True

gc.collect(generation=2)

若被呼叫時沒有引數,則啟動完整垃圾回收。可選的引數 generation 可以是一個指明需要回收哪一代垃圾的整數(從 0 到 2)。當引數 generation 無效時,會引發 ValueError 例外。發現的不可達物件數目會被回傳。

每當執行完整回收或最高代 (2) 回收時,為多個內建型別所維護的空閒列表會被清空。為了特定型別的實現,特別是 float,在某些空閒列表中並非所有項目都會被釋放。

當直譯器已經執行收集時呼叫 gc.collect() 的效果是未定義的。

gc.set_debug(flags)

設定垃圾回收器的除錯旗標。除錯資訊會被寫入 sys.stderr。請見下方的除錯旗標列表,可以使用位元操作 (bit operation) 進行設定以控制除錯程式。

gc.get_debug()

回傳當前設置的除錯旗標。

gc.get_objects(generation=None)

回傳一個包含回收器正在追蹤的所有物件的 list,除去所回傳的 list。如果 generation 不為 None,只回傳回收器正在追蹤且屬於該代的物件。

在 3.8 版的變更: 新增 generation 參數。

引發一個附帶引數 generation稽核事件 (auditing event) gc.get_objects

gc.get_stats()

回傳一個包含三個字典物件的 list,每個字典分別包含對應代中自從直譯器開始執行後的垃圾回收統計資料。字典的鍵的數目在將來可能會改變,但目前每個字典包含以下項目:

  • collections 是該代被回收的次數;

  • collected 是該代中被回收的物件總數;

  • uncollectable 是在這一代中被發現無法回收的物件總數(因此被移到 garbage list 中)。

在 3.4 版被加入.

gc.set_threshold(threshold0[, threshold1[, threshold2]])

設定垃圾回收閾值(回收頻率)。 將 threshold0 設為零會停止回收。

垃圾回收器會根據物件在多少次垃圾回收後仍倖存來把所有物件分類為三代。新建物件會被放在最年輕代(第 0 代)。 如果一個物件在一次垃圾回收後倖存,它會被移入下一個較老代。由於第 2 代是最老代,這一代的物件在一次垃圾回收後仍會保留原樣。為了確定何時要執行,垃圾回收器會追蹤自上一次回收後物件分配和釋放的數量。當分配數量減去釋放數量的結果大於 threshold0 時,垃圾回收就會開始。初始時只有第 0 代會被檢查。如果自第 1 代被檢查後第 0 代已被檢查超過 threshold1 次,則第 1 代也會被檢查。對於第三代來說,情況還會更復雜一些,請參閱 Collecting the oldest generation 來了解詳情。

gc.get_count()

將當前回收計數以 (count0, count1, count2) 形式的 tuple 回傳。

gc.get_threshold()

將當前回收閾值以 (threshold0, threshold1, threshold2) 形式的 tuple 回傳。

gc.get_referrers(*objs)

回傳包含直接參照 objs 中任一個物件的物件 list。這個函式只定位支援垃圾回收的容器;參照了其它物件但不支援垃圾回收的擴充套件型別無法被找到。

需要注意的是,已經解除參照的物件,但仍存在於參照迴圈中未被回收時,該物件仍然會被作為參照者出現在回傳的 list 中。若只要獲取當前正在參照的物件,需要在呼叫 get_referrers() 之前呼叫 collect()

警告

在使用 get_referrers() 回傳的物件時必須要小心,因為其中的一些物件可能仍在建構中而處於暫時無效的狀態。不要把 get_referrers() 用於除錯以外的其它目的。

引發一個附帶引數 objs稽核事件 gc.get_referrers

gc.get_referents(*objs)

回傳包含被任意一個引數直接參照之物件的 list。回傳的被參照物件是有被引數的 C 語言級別 tp_traverse 方法(若存在)訪問到的物件,可能不是所有的實際直接可達物件。只有支援垃圾回收的物件支援 tp_traverse 方法,並且此方法只會訪問涉及參照迴圈的物件。因此,可以有以下例子:一個整數對於一個引數是直接可達的,這個整數物件有可能出現或不出現在結果的 list 當中。

引發一個附帶引數 objs稽核事件 gc.get_referents

gc.is_tracked(obj)

當物件正在被垃圾回收器追蹤時回傳 True,否則回傳 False。一般來說,原子型別 (atomic type) 的實例不會被追蹤,而非原子型別(如容器、使用者自己定義的物件)會被追蹤。然而,有一些特定型別最佳化會被用來減少垃圾回收器在簡單實例(如只含有原子性的鍵和值的字典)上的足跡:

>>> gc.is_tracked(0)
False
>>> gc.is_tracked("a")
False
>>> gc.is_tracked([])
True
>>> gc.is_tracked({})
False
>>> gc.is_tracked({"a": 1})
False
>>> gc.is_tracked({"a": []})
True

在 3.1 版被加入.

gc.is_finalized(obj)

如果給定物件已被垃圾回收器終結則回傳 True,否則回傳 False。:

>>> x = None
>>> class Lazarus:
...     def __del__(self):
...         global x
...         x = self
...
>>> lazarus = Lazarus()
>>> gc.is_finalized(lazarus)
False
>>> del lazarus
>>> gc.is_finalized(x)
True

在 3.9 版被加入.

gc.freeze()

凍結 (freeze) 垃圾回收器所追蹤的所有物件;將它們移至永久代並忽略所有未來的收集動作。

如果一個行程將在沒有 exec() 的情況下進行 fork(),避免子行程中不必要的寫入時複製將最大化記憶體共享並減少整體記憶體使用。這需要避免在父行程的記憶體頁面中建立已釋放的「漏洞」,並確保子行程中的 GC 收集不會觸及源自父行程的長壽命物件的 gc_refs 計數器。要實現這兩個目標,請在父行程的早期呼叫 gc.disable(),在 fork() 之前呼叫 gc.freeze(),並儘早在子行程中呼叫 gc.enable()

在 3.7 版被加入.

gc.unfreeze()

解凍 (unfreeze) 永久代中的物件,並將它們放回到最年老代中。

在 3.7 版被加入.

gc.get_freeze_count()

回傳永久代中的物件數量。

在 3.7 版被加入.

以下變數僅供唯讀存取(你可以修改其值但不應該重新繫結 (rebind) 它們):

gc.garbage

一個回收器發現不可達而又無法被釋放的物件(不可回收物件)list。從 Python 3.4 開始,該 list 在大多數時候都應該是空的,除非使用了有非 NULL tp_del 槽位的 C 擴充套件型別的實例。

如果設定了 DEBUG_SAVEALL,則所有不可達物件將被加進該 list 而不會被釋放。

在 3.2 版的變更: interpreter shutdown 即直譯器關閉時,若此 list 非空,會產生 ResourceWarning,在預設情況下此警告不會被提醒。如果設定了 DEBUG_UNCOLLECTABLE,所有無法被回收的物件會被印出。

在 3.4 版的變更: 根據 PEP 442,帶有 __del__() method 的物件最終不會在 gc.garbage 內。

gc.callbacks

會被垃圾回收器在回收開始前和完成後呼叫的一系列回呼函式 (callback) 。這些回呼函式在被呼叫時附帶兩個引數:phaseinfo

phase 可為以下兩者之一:

"start":垃圾回收即將開始。

"stop":垃圾回收已結束。

info 是一個字典,提供回呼函式更多資訊。已有定義的鍵有:

"generation"(代):正在被回收的最年老的一代。

"collected"(已回收的):當 phase 為 "stop" 時,被成功回收的物件的數目。

"uncollectable"(不可回收的):當 phase 為 "stop" 時,不能被回收並被放入 garbage 的物件的數目。

應用程式可以把他們自己的回呼函式加入此 list。主要的使用場景有:

收集垃圾回收的統計資料,如:不同代的回收頻率、回收任務所花費的時間。

讓應用程式可以識別和清理他們自己在 garbage 中的不可回收型別物件。

在 3.3 版被加入.

以下常數是為了和 set_debug() 一起使用所提供:

gc.DEBUG_STATS

在回收完成後印出統計資訊。當調校回收頻率設定時,這些資訊會很有用。

gc.DEBUG_COLLECTABLE

當發現可回收物件時印出資訊。

gc.DEBUG_UNCOLLECTABLE

印出找到的不可回收物件的資訊(指不能被回收器回收的不可達物件)。這些物件會被新增到 garbage list 中。

在 3.2 版的變更: interpreter shutdown(直譯器關閉)時,若 garbage list 不是空的,那這些內容也會被印出。

gc.DEBUG_SAVEALL

設定後,所有回收器找到的不可達物件會被加進 garbage 而不是直接被釋放。這在為一個記憶體流失的程式除錯時會很有用。

gc.DEBUG_LEAK

要印出記憶體流失程式之相關資訊時,回收器所需的除錯旗標。(等同於 DEBUG_COLLECTABLE | DEBUG_UNCOLLECTABLE | DEBUG_SAVEALL)。