python清除變數
Ⅰ python 用del刪除變數以後為什麼還是OOM(Python的內存管理與垃圾回收)
本文使用 Zhihu On VSCode 創作並發布
目錄:
一、前言 Preface
我一直以來沒怎麼認真學過python的內存釋放機制,對於這東西總處於一種一知半解的情況。總以為我del 一個變數,那就自動在內存里刪除了這個變數,自然而然地內存就被釋放了。
然而,目前我工作剛滿一年,在這一年的時光里,我遇到三四次無法理解的OOM錯誤,讓我不得不認真的research一下單純的del 到底能不能做到我想做的事。
我自己雖說一直有個讀博的想法,但是在工作中為了效率,其實很多時候能用就行,並不用達到知其然,且知其所以然 的程度。所以我先調查到了一些問題出現的原因以及解決方法,最後再學習一下Python自己的內存回收機制。
Without further ado, let's start.二、實用正題 Practical part
從這篇博文 中,我們可以看到 必須要 import gc 然後用 gc.collect() 去回收已經 del 的大文件。在博文中,作者提到了用一個自定義函數清除環境中所有的全局變數。可能用得上,就轉載記錄到這里。
三、小學一點 Learn a little bit.python的內存管理方式
這是最新的Python-3.10 的關於內存管理的文檔,文章長度很短,可以花兩分鍾閱讀一下。(不過我也讀不懂,或許應該讀 gc 的文檔)
准備知識: 關於變數與指向的對象
背景知識: from here
在編程中,程序的對象存儲在內存中以供快速訪問。在許多編程語言中,程序代碼中的變數實際上只是一個指向內存中對象地址的指針。當變數被使用時,進程會從內存讀取其值並對其進行操作。在早期的編程語言中,開發者需要手動管理程序的所有內存。這意味著在創建列表或對象之前,你需要先分配變數的內存。完成對變數的操作後,你需要釋放內存,以便其他人使用。這導致了兩個問題:忘記釋放內存。如果不釋放使用完畢的內存,會導致內存泄漏,導致程序隨著時間的推移使用過多內存。過早釋放內存。第二種類型的問題是過早釋放仍然被使用的內存。這可能導致程序崩潰,因為它嘗試訪問不存在的內存值,或者可能導致數據損壞。引用一個已經釋放內存的對象稱為懸掛指針。
因此,現代語言中都採用了自動內存管理和垃圾回收機制。Python中採用以下策略實現內存回收。
3.1 引用計數 (Reference count)
在Python中,每個對象都有指向該對象的引用總數---引用計數
在Python中,每一個對象的核心是一個PyObject結構體,它包含一個引用計數器(ob_refcnt)。程序運行時實時更新這個計數器的值,反映當前對象被引用的數量。當對象的引用計數值為0,內存就會立即釋放。查看對象引用計數的方法是使用sys.getrefcount()。
基本原理是,一個Python對象的引用計數在對象被引用時增加,在對象被引用解除時減少。當對象的引用計數為0,內存就被釋放。
導致引用計數加一的情況:
導致引用計數減一的情況:
舉例
引用計數的優點 (pros)
高效、實時,一旦一個對象的引用計數歸零,內存就直接釋放。無需等待特定時機,釋放內存時間在程序運行過程中,程序運行比較平穩
引用計數的缺點 (cons)
雖然邏輯簡單,但實現有些復雜。每個對象都需要分配單獨的空間來統計引用計數,並需要維護這個計數
在某些情況下,可能會比較慢。通常垃圾回收平穩運行,但當需要釋放大型對象時,如字典,需要對引用的所有對象進行嵌套循環調用,可能花費較長時間。
循環引用 (Circular References),這是引用計數難以解決的問題,需要使用其他垃圾回收演算法進行補充。
3.2 標記清除 (Mark and Sweep)
Python採用「標記-清除」(Mark and Sweep)演算法解決容器對象可能產生的循環引用問題。(注意,只有容器對象才會產生循環引用,如列表、字典、自定義類對象、元組等。數字、字元串等簡單類型不會出現循環引用。作為一種優化策略,對於只包含簡單類型的元組也不在標記清除演算法的考慮之列)
循環引用示例
對於循環引用問題,比如兩個對象互相引用對方,當它們各自沒有其他引用(即引用計數都只有1),如果能識別出這個循環引用,將它們的計數減去,就可以看到它們的真實引用計數。為此,有一種方法,例如從對象A出發,沿著引用找到對象B,將B的引用計數減1;然後從B返回到A,將A的計數減1,這樣可以去除這個循環引用關系。不過,還有一個需要考慮的地方。如果A只單向引用B,在找到B之前不知道B是否也引用A,先減去B的計數可能會讓B成為不可回收的對象。為了解決這個問題,Python常將內存塊一分為二,一部分用於保存真正的引用計數,另一部分用於引用計數副本,在副本上進行實驗。例如,在副本中維護兩個鏈表,一個放不可回收的對象集合,另一個放被標記為可以回收的對象(計數減為0),然後在後者中找一些被前者中對象直接或間接單向引用的對象,將它們移動到前者的表中。這樣可以確保不應該被回收的對象不會被回收,應該被回收的對象都被回收。
3.3 分代回收 (Generational garbage collection)
這是一種以空間換取時間的方法。分代回收基於這樣的統計事實:程序中存在一定比例的內存塊生存周期較短;剩下的內存塊,生存周期較長,甚至從程序開始到程序結束。生存期較短的對象比例通常在 80%~90% 之間。這種思想簡單地說就是:對象存在時間越長,越可能是非垃圾,應該越少去收集。在執行標記-清除演算法時,可以有效減少遍歷的對象數,從而提高垃圾回收速度。Python gc給對象定義了三種世代(0,1,2),每一個新生對象在generation zero中,如果它在一輪gc掃描中活了下來,那麼它將被移至generation one,在那裡它將較少地被掃描,如果它又活過了一輪gc,它又將被移至generation two,在那裡它被掃描的次數將會更少。gc的掃描觸發時機是當某一世代中被分配的對象與被釋放的對象之差達到某一閾值時。值得注意的是,當某一世代的掃描被觸發時,比該世代年輕的世代也會被掃描。也就是說,如果世代2的gc掃描被觸發,世代0,世代1也將被掃描;如果世代1的gc掃描被觸發,世代0也會被掃描。
該閾值可以通過下面兩個函數查看和調整:
常用函數:
如果垃圾回收不易理解,我們可以用現實生活中的例子來聯想。開發商拍地,房管局登記開發商捂地的數量,增加或減少。這就是引用計數。如果地出現糾紛,陷入循環死結,政府會分別處理,各個擊破。這就是標記-清除。如果開發商後台強大,捂地不開發,地方政府只能採取一貫做法,「讓後代去解決」。這就是分代回收。關於set_threshold()中的三個參數threshold0, threshold1, threshold2的介紹:gc會記錄自從上次收集以來新分配的對象數量與釋放的對象數量,當兩者之差超過threshold0的值時,gc的掃描就會啟動,初始時只有世代0被檢查。如果自從世代1最近一次被檢查以來,世代0被檢查超過 threshold_1 次,那麼對世代1的檢查將被觸發。相同的,如果自從世代2最近一次被檢查以來,世代1被檢查超過 threshold_2 次,那麼對世代2的檢查將被觸發。get_threshold()是獲取三者的值,默認值為(700,10,10)。
Ⅱ 如何配置python的環境變數
如何配置Python的環境變數:
答案明確:
1. 打開系統設置。
2. 進入環境變數設置。
3. 新建系統環境變數,變數名為「PYTHONPATH」,變數值為Python安裝路徑。
4. 或者編輯Path環境變數,將Python安裝路徑添加到已有變數中。
詳細解釋:
步驟一:打開系統設置。
操作系統不同,打開系統設置的方式可能會有所不同。例如在Windows系統中,可以通過搜索「系統環境變數」來找到相關設置;在Linux或Mac系統中,則可以在終端使用特定命令來查看和編輯環境變數。
步驟二:進入環境變數設置。
環境變數是操作系統中用於指定操作系統運行環境的一些參數。在系統設置中,可以找到一個或多個與環境變數相關的選項。在Windows系統中,環境變數通常可以在「系統屬性」下的「高級」選項卡中找到。
步驟三:配置Python環境變數。
有兩種主要方式配置Python的環境變數。一種方式是新建系統環境變數,變數名為「PYTHONPATH」,這樣可以讓操作系統識別Python的安裝路徑。另一種方式是通過編輯Path環境變數,將Python的安裝路徑添加到已有的變數中。這樣做的好處是可以在命令行直接運行Python及其腳本。
配置環境變數的具體步驟可能會因操作系統的不同而有所差異,但基本原理是相同的。按照上述步驟操作後,就可以成功配置Python的環境變數,從而方便在系統中運行Python程序。
Ⅲ 已知變數string=' python是一種解釋型語言 '將變數string中的兩側空格去除並將字母'p'替換為大寫字母'P'
給你寫出來了,看一下
Ⅳ python怎麼設置環境變數
Python設置環境變數的方法有多種,具體取決於你的操作系統和環境管理工具。以下是在不同操作系統上設置Python環境變數的常見方法:
一、在Windows上設置Python環境變數
1. 打開「我的電腦」或「此電腦」,右鍵點擊「屬性」。
2. 選擇「高級系統設置」。
3. 在系統屬性窗口中,點擊「環境變數」按鈕。
4. 在「系統變數」或「用戶變數」部分,點擊「新建」,然後添加你的Python環境變數。
二、在Linux或Mac上設置Python環境變數
1. 打開終端。
2. 使用export命令設置環境變數,例如:`export PYTHONPATH=/path/to/your/python/directory`。這將臨時添加環境變數,當終端會話關閉後,環境變數將失效。
3. 若要永久設置環境變數,需要在shell的配置文件中添加export命令,然後重新載入配置文件或使用source命令使其立即生效。
詳細解釋:
在Windows系統中,環境變數是在系統屬性中設置的,可以通過「高級系統設置」找到相關選項。在Linux和Mac系統中,環境變數通常在終端中使用export命令設置。值得注意的是,使用export命令設置的環境變數只在當前終端會話中有效,如果想要永久設置環境變數,需要在相應的配置文件中添加export命令並保存。這樣,每次啟動新的終端會話時,這些環境變數就會自動載入。
對於Python特定的環境變數,如PYTHONPATH,通常用於指定Python查找模塊和包的路徑。通過設置這些環境變數,可以影響Python的運行方式和行為。因此,在開發和運行過程中,根據需要設置合適的環境變數是非常重要的。