簡體   English   中英

泄露TarInfo對象

[英]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列表將繼續增長。 這樣可以使用getmembersgetmember方法,但這只會對您的用例造成麻煩。 似乎最好的解決方法是在迭代時繼續清除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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM