将大文件写入blob存储并耗尽内存

时间:2012-01-17 16:30:18

标签: python google-app-engine

我正在使用实验性blobstore文件API来编写包含某些事件数据的CSV文件。有很多数据所以我正在批量写入。我的代码在后端运行,所以我有很多时间,但我的内存不足,我不明白为什么。

以下是代码:

from __future__ import with_statement
from google.appengine.api import files

q = Event.all()

events = q.fetch(50)
while events:
    with files.open(blobname, 'a') as f:
        buf = StringIO()

        for event in events:
            buf.write(event.id)
            buf.write(',')
            buf.write(`event.logged`)
            buf.write(',')
            buf.write(event.type)
            buf.write(',')
            buf.write(event.timestamp)
            buf.write(',')

            needAmpersand = False
            for prop in event.dynamic_properties():
                if needAmpersand:
                    buf.write('&')
                needAmpersand = True
                buf.write(prop + '=' + str(getattr(event, prop)))
            buf.write('\n')

        f.write(buf.getvalue())
        buf.close()

    events = q.fetch(50)

files.finalize(blobname)

此代码使while循环事件循环大约20次,然后进程中止耗尽了超过140 mb的内存。 Event是特定于此应用程序的数据库模型。事件基本上是远程计算机上发生的事情的记录,稍后这些事件将通过map reduce操作来处理以构建统计信息,现在我只想下载它们。我们的数据库中有100个事件中有100个(稍后我们也会切换到以不同方式存储它们,但现在就是这样)。

我注意到with f.open每次完成with子句时都会调用f.close,因为f.close()调用了f.__exit__()

此代码的早期实例化仅在写入'StringIO'的每个元素上调用f.write(..)。这个早期版本的内存耗尽得更快,但其他方面表现相似。这段代码还有一些东西会导致内存泄漏。

帮助?

更新 我刚刚尝试注释掉f.write(buf.getvalue()),虽然它显然没有创建一个包含任何内容的blobstore项,但它最终完成了处理所有Event实体。我错过了什么或f.write()泄漏内存或缓冲所有内容,直到finalize()?

1 个答案:

答案 0 :(得分:1)

当你致电f.write(buf.getvalue())时,你要求StringIO将自己变成一个内存对象并传递它。这将是昂贵的。

尝试buf.seek(0),它将回退到流的开头,然后只传递f.write(buf)StringIO是一个类似文件的对象,f.write应该能够将其作为流读取。

查看source,从文档或代码中不清楚file_service_pb.AppendRequest是否可以处理StringIO。试试吧。