[英]Leaking TarInfo objects
我有一個Python實用程序,它tar.xz
文件並處理每個單獨的文件。 這是一個15MB的壓縮文件,包含740MB的未壓縮數據。
在內存非常有限的一台特定服務器上,程序因內存不足而崩潰。 我使用objgraph來查看創建了哪些對象。 事實證明, TarInfo
實例尚未發布。 主循環類似於:
with tarfile.open(...) as tar:
while True:
next = tar.next()
stream = tar.extractfile(next)
process_stream()
iter+=1
if not iter%1000:
objgraph.show_growth(limit=10)
輸出非常一致:
TarInfo 2040 +1000
TarInfo 3040 +1000
TarInfo 4040 +1000
TarInfo 5040 +1000
TarInfo 6040 +1000
TarInfo 7040 +1000
TarInfo 8040 +1000
TarInfo 9040 +1000
TarInfo 10040 +1000
TarInfo 11040 +1000
TarInfo 12040 +1000
這一直持續到所有30,000個文件都被處理完畢。
為了確保,我已經注釋掉了創建流並處理流的行。 內存使用情況保持不變 - TarInfo實例泄露。
我正在使用Python 3.4.1,這種行為在Ubuntu,OS X和Windows上是一致的。
看起來這實際上是設計的。 該TarFile
對象維護所有的列表TarInfo
對象包含的members
屬性。 每次調用next
,它從存檔中提取的TarInfo
對象都會添加到列表中:
def next(self):
"""Return the next member of the archive as a TarInfo object, when
TarFile is opened for reading. Return None if there is no more
available.
"""
self._check("ra")
if self.firstmember is not None:
m = self.firstmember
self.firstmember = None
return m
# Read the next block.
self.fileobj.seek(self.offset)
tarinfo = None
... <snip>
if tarinfo is not None:
self.members.append(tarinfo) # <-- the TarInfo instance is added to members
當您提取更多項目時, members
列表將繼續增長。 這樣可以使用getmembers
和getmember
方法,但這只會對您的用例造成麻煩。 似乎最好的解決方法是在迭代時繼續清除members
屬性(如此處所示 ):
with tarfile.open(...) as tar:
while True:
next = tar.next()
stream = tar.extractfile(next)
process_stream()
iter+=1
tar.members = [] # Clear members list
if not iter%1000:
objgraph.show_growth(limit=10)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.