![](/img/trans.png)
[英]memory leak while adding elements from text file to dictionary in python
[英]Python - Strange Memory Leak While Reading From File
我遇到一個奇怪的問題,在Python2中從文件讀取時發生奇怪的內存泄漏。
我試圖消除泄漏的代碼達幾個小時,但失敗了。 然后,我試圖隔離泄漏的代碼,並編寫了一個最小的程序來再現相同的泄漏。 這里是:
import sys
import re
@profile
def leak(filename):
residual_line = []
with open(filename) as f:
for line in f:
splitted_line = re.split(r' |\n', line)
del line
filtered_line = filter(lambda x: x != '', splitted_line)
del splitted_line
filtered_line = residual_line + filtered_line
for x in range(0,len(filtered_line)):
a=5
residual_line = filtered_line
del filtered_line
del residual_line
@profile
def main():
filename = sys.argv[1]
leak(filename)
sys.exit(0)
main()
我正在使用memory_profiler模塊對其進行性能分析,這是性能分析的輸出:
如您所見,內存分配發生在第8行,但從未釋放。 泄漏為31 KiB,我嘗試讀取的文件為3.4kB。 如果我將文件大小加倍,泄漏將變為70KiB,再將160KiB加倍,因此泄漏可能取決於文件。
我希望有人能找到泄漏,在此先感謝。
我懷疑是否存在內存泄漏,我只是覺得您的方法來自對Python內存分配工作原理的缺乏了解。
內存分配在Python中有多個層次。 有系統自己的分配器,當您使用Windows任務管理器或ps檢查內存使用情況時,就會顯示該分配器。 然后是C運行時的內存分配器(malloc),它從系統分配器獲取內存,並將其以較小的塊分發給應用程序。 最后,還有Python自己的對象分配器,該對象分配器用於最多256個字節的對象。 該分配器從C分配器獲取大塊內存,並使用針對Python精心調整的算法將它們切成小塊。
這是一個演示此示例的示例:首先創建一個對象,將其刪除,然后收集剩余的變量:
import gc
@profile
def create_list():
lst = list(range(1000000))
del lst
gc.collect()
if __name__ == '__main__':
create_list()
結果如下:
└──> python -m memory_profiler test.py
Filename: test.py
Line # Mem usage Increment Line Contents
================================================
3 20.414 MiB 0.000 MiB @profile
4 def create_list():
5 51.461 MiB 31.047 MiB lst = list(range(1000000))
6 43.828 MiB -7.633 MiB del lst
7 26.793 MiB -17.035 MiB gc.collect()
如果您注意到,大多數內存將永遠不會返回到系統,而是保留在Python分配器或C分配器中。
如果我對文件執行相同的操作,則會得到相同的結果:
import gc
@profile
def iter_file():
with open('/path/to/somefile') as f:
for line in f:
del line
gc.collect()
if __name__ == '__main__':
iter_file()
結果如下:
└──> python -m memory_profiler test.py
Filename: test.py
Line # Mem usage Increment Line Contents
================================================
3 20.496 MiB 0.000 MiB @profile
4 def iter_file():
5 20.496 MiB 0.000 MiB with open('/path/to/somefile') as f:
6 20.801 MiB 0.305 MiB for line in f:
7 20.613 MiB -0.188 MiB del line
8 20.613 MiB 0.000 MiB gc.collect()
簡而言之,不必擔心內存泄漏:只要確保變量超出范圍,Python就會為您處理。
這也意味着您不必刪除每個新創建的變量:當重新定義該變量,超出范圍時,將自動對其進行垃圾回收,並將內存返回給分配器,甚至還可能返回給系統。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.