成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Python 內存管理的工作原理,你了解嗎?

譯文 精選
開發 后端
Python 為開發者提供了許多便利,其中最大的便利之一是其幾乎無憂的內存管理。

Python 為開發者提供了許多便利,其中最大的便利之一是其幾乎無憂的內存管理。開發者無需手動為 Python 中的對象和數據結構分配、跟蹤和釋放內存。運行時會為你完成所有這些工作,因此你可以專注于解決實際問題,而不是爭論機器級細節。

盡管如此,即使是經驗不多的 Python 用戶,了解 Python 的垃圾收集和內存管理是如何工作的也是有好處的。了解這些機制將幫助你避免更復雜的項目可能出現的性能問題。你還可以使用 Python 的內置工具來監控程序的內存管理行為。

Python如何管理內存

每個 Python 對象都有一個引用計數,也稱為引用計數。 refcount 是持有對給定對象的引用的其他對象總數的計數。當你添加或刪除對對象的引用時,數字會上升或下降。當一個對象的引用計數變為零時,該對象將被釋放并釋放其內存。

什么是參考?允許通過名稱或通過另一個對象中的訪問器訪問對象的任何內容。

這是一個簡單的例子:

x = "Hello there"

當我們向 Python 發出這個命令時,引擎蓋下會發生兩件事:

  1. 該字符串"Hello there"作為 Python 對象創建并存儲在內存中。
  2. 該名稱x在本地命名空間中創建并指向該對象,這會將其引用計數增加 1 到 1。

如果我們說y = x,那么引用計數將再次提高到 2。

每當xandy超出范圍或從它們的命名空間中刪除時,對于每個名稱,字符串的引用計數都會減少 1。一旦x和y都超出范圍或被刪除,字符串的引用計數變為 0 并被刪除。

現在,假設我們創建了一個包含字符串的列表,如下所示:

x = ["Hello there", 2, False]

字符串保留在內存中,直到列表本身被刪除或包含字符串的元素從列表中刪除。這些操作中的任何一個都將導致唯一持有對字符串的引用的事物消失。

現在考慮這個例子:

x = "Hello there" y = [x]

如果我們從 中刪除第一個元素y,或者完全刪除列表y,則字符串仍在內存中。這是因為名稱x包含對它的引用。

Python 中的引用循環

在大多數情況下,引用計數工作正常。但有時你會遇到兩個對象各自持有對彼此的引用的情況。這稱為 參考周期。在這種情況下,對象的引用計數永遠不會達到零,也永遠不會從內存中刪除。

這是一個人為的例子:

x = SomeClass()
y = SomeOtherClass()
x.item = y
y.item = x

由于x并y持有彼此的引用,因此它們永遠不會從系統中刪除——即使沒有其他任何東西引用它們中的任何一個。

Python 自己的運行時為對象生成引用循環實際上是相當普遍的。一個示例是帶有包含對異常本身的引用的回溯對象的異常。

在Python的早期版本中,這是一個問題。具有引用周期的對象可能會隨著時間的推移而累積,這對于長時間運行的應用程序來說是一個大問題。但 Python 此后引入了循環檢測和垃圾收集系統,用于管理引用循環。

Python 垃圾收集器 (gc)

Python 的垃圾收集器檢測具有引用周期的對象。它通過跟蹤作為“容器”的對象(例如列表、字典、自定義類實例)并確定其中的哪些對象無法在其他任何地方訪問來實現這一點。

一旦這些對象被挑選出來,垃圾收集器就會通過確保它們的引用計數可以安全地降為零來刪除它們。

絕大多數 Python 對象沒有引用周期,因此垃圾收集器不需要 24/7 運行。相反,垃圾收集器使用一些啟發式方法來減少運行頻率,并且每次都盡可能高效地運行。

當 Python 解釋器啟動時,它會跟蹤已分配但未釋放的對象數量。絕大多數 Python 對象的生命周期都很短,因此它們會迅速出現和消失。但隨著時間的推移,更多長壽的物體會出現。一旦超過一定數量的此類對象堆積起來,垃圾收集器就會運行。

每次垃圾收集器運行時,它都會收集所有在收集中幸存下來的對象,并將它們放在一個稱為一代的組中。這些“第一代”對象在參考周期中被掃描的頻率較低。任何在垃圾收集器中幸存下來的第一代對象最終都會遷移到第二代,在那里它們被掃描得更少。

同樣,垃圾收集器不會跟蹤所有內容。例如,像用戶創建的類這樣的復雜對象總是被跟蹤。但是不會跟蹤僅包含簡單對象(如整數和字符串)的字典,因為該特定字典中的任何對象都不會包含對其他對象的引用。不能保存對其他元素(如整數和字符串)的引用的簡單對象永遠不會被跟蹤。

如何使用 gc 模塊

通常,垃圾收集器不需要調整即可運行良好。Python 的開發團隊選擇了反映最常見現實世界場景的默認值。但是如果你確實需要調整垃圾收集的工作方式,你可以使用Python 的 gc 模塊。該gc模塊為垃圾收集器的行為提供編程接口,并提供對正在跟蹤的對象的可見性。

gc當你確定不需要垃圾收集器時,你可以做的一件有用的事情是關閉它。例如,如果你有一個堆放大量對象的短運行腳本,則不需要垃圾收集器。腳本結束時,所有內容都將被清除。為此,你可以使用命令禁用垃圾收集器gc.disable()。稍后,你可以使用 重新啟用它gc.enable()。

你還可以使用 手動運行收集周期gc.collect()。一個常見的應用是管理程序的性能密集型部分,該部分會生成許多臨時對象。你可以在程序的該部分禁用垃圾收集,然后在最后手動運行收集并重新啟用收集。

另一個有用的垃圾收集優化是gc.freeze(). 發出此命令時,垃圾收集器當前跟蹤的所有內容都被“凍結”,或者被列為免于將來的收集掃描。這樣,未來的掃描可以跳過這些對象。如果你有一個程序在啟動之前導入庫并設置大量內部狀態,那么你可以gc.freeze()在所有工作完成后發出。這使垃圾收集器不必搜尋那些無論如何都不太可能被刪除的東西。(如果你想對凍結的對象再次執行垃圾收集,請使用gc.unfreeze().)

使用 gc 調試垃圾收集

你還可以使用它gc來調試垃圾收集行為。如果你有過多的對象堆積在內存中并且沒有被垃圾收集,你可以使用gc's 檢查工具來找出可能持有對這些對象的引用的對象。

如果你想知道哪些對象持有對給定對象的引用,可以使用gc.get_referrers(obj)列出它們。你還可以使用gc.get_referents(obj)來查找給定對象引用的任何對象。

如果你不確定給定對象是否是垃圾收集的候選對象,gc.is_tracked(obj)請告訴你垃圾收集器是否跟蹤該對象。如前所述,請記住垃圾收集器不會跟蹤“原子”對象(例如整數)或僅包含原子對象的元素。

如果你想親自查看正在收集哪些對象,可以使用 設置垃圾收集器的調試標志gc.set_debug(gc.DEBUG_LEAK|gc.DEBUG_STATS)。這會將有關垃圾收集的信息寫入stderr。它將所有作為垃圾收集的對象保留在只讀列表中。

避免 Python 內存管理中的陷阱

如前所述,如果你在某處仍有對它們的引用,則對象可能會堆積在內存中而不會被收集。這并不是 Python 垃圾收集本身的失敗。垃圾收集器無法判斷你是否不小心保留了對某物的引用。

讓我們以一些防止對象永遠不會被收集的指針作為結尾。

注意對象范圍

如果你將對象 1 指定為對象 2 的屬性(例如類),則對象 2 將需要超出范圍,然后對象 1 才會:

obj1 = MyClass()
obj2.prop = obj1

更重要的是,如果這種情況發生在某種其他操作的副作用中,例如將對象 2 作為參數傳遞給對象 1 的構造函數,你可能不會意識到對象 1 持有一個引用:

obj1 = MyClass(obj2)

另一個例子:如果你將一個對象推入模塊級列表并忘記該列表,則該對象將一直保留,直到從列表中刪除,或者直到列表本身不再有任何引用。但是如果該列表是一個模塊級對象,它可能會一直存在,直到程序終止。

簡而言之,請注意你的對象可能被另一個看起來并不總是很明顯的對象持有的方式。

使用 weakref避免引用循環

Python 的 weakref 模塊允許你創建對其他對象的弱引用。弱引用不會增加對象的引用計數,因此只有弱引用的對象是垃圾回收的候選對象。

一個常見的用途weakref是對象緩存。你不希望僅僅因為它具有緩存條目而保留引用的對象,因此你將 aweakref用于緩存條目。

手動中斷參考循環

最后,如果你知道給定對象包含對另一個對象的引用,你總是可以手動中斷對該對象的引用。例如,如果你有instance_of_class.ref = other_object,你可以設置instance_of_class.ref = None何時準備刪除 instance_of_class。

通過了解 Python 內存管理的工作原理,我們對其垃圾收集系統如何幫助優化 Python 程序中的內存,以及如何使用標準庫和其他地方提供的模塊來控制內存使用和垃圾收集。

原文標題:??Python garbage collection and the gc module??

責任編輯:黃顯東 來源: 51CTO
相關推薦

2020-05-13 08:10:32

HTTPS安全網站

2023-12-10 13:37:23

Python編程上下文管理

2019-11-12 14:40:43

CPU緩存內存

2023-11-06 07:23:06

API開發生態系統

2021-11-30 07:51:29

共享內存進程

2023-12-08 14:13:00

MemrayPython內存

2021-02-07 09:02:28

內存管理length

2009-12-17 11:37:39

Linux網卡

2018-11-20 09:37:19

Java內存模型

2024-08-02 14:52:00

2019-10-31 08:36:59

線程內存操作系統

2011-08-08 15:14:11

PPPOE

2012-09-27 10:24:22

監控機房

2020-10-21 09:28:25

JS變量的內存分配

2022-07-26 00:00:22

HTAP系統數據庫

2012-09-06 17:54:28

2014-04-17 16:42:03

DevOps

2018-11-21 09:32:10

IT云計算

2012-02-06 13:52:33

JavaScript

2025-01-03 08:09:15

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本一区二区视频 | 国产精品91久久久久久 | av色站| 久久久女| 久久精品亚洲精品国产欧美 | 日韩伦理一区二区 | 狼人伊人影院 | 国产精品久久久久久妇女6080 | 国产在线观看一区二区三区 | 日韩超碰 | 97超碰成人 | 亚洲精品免费观看 | 国产精品成人一区二区三区夜夜夜 | 久久久精品一区二区三区 | 亚洲精品久久视频 | 精品成人一区 | 91免费在线看 | 艹逼网| 亚洲免费视频一区 | 久久夜色精品国产 | 久久中文字幕在线 | 久久久蜜桃 | www精品| 在线观看免费黄色片 | 久久亚洲精品久久国产一区二区 | 日韩伦理一区二区三区 | 日韩av一区二区在线观看 | 成人在线看片 | 日本一区二区三区四区 | 亚洲综合三区 | 成人免费网站www网站高清 | 亚洲精品一区二区三区在线观看 | 国产精品久久久久久久久久久久 | 亚洲精品电影网在线观看 | 欧美黑人又粗大 | 国产精品久久亚洲 | 久久一二| 国产精品无码专区在线观看 | 久久久视频在线 | 欧美激情在线一区二区三区 | 国产精品99久久久久久www |