Python 将大文件写入blob存储并耗尽内存
我正在使用实验性的blobstore文件API编写一个包含一些事件数据的CSV文件。有很多数据,所以我正在批量写入。我的代码在后台运行,所以我有很多时间,但我的内存不足,我不明白为什么 代码如下:Python 将大文件写入blob存储并耗尽内存,python,google-app-engine,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(b
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的内存后中止。事件是特定于此应用程序的数据库模型。事件基本上是远程机器上发生的事件的记录,稍后这些事件将由map reduce操作处理以生成统计数据,现在我只想下载它们。我们的数据库中有1000个事件中的100个(稍后我们也将切换到以不同的方式存储它们,但目前仅此而已)
我注意到withf.open
导致每次完成with子句时调用f.close
,因为f.close()
由f
这段代码的一个早期实例只是在写入“StringIO”的每个元素上调用了f.write(..)。这个早期版本的内存耗尽速度快得多,但在其他方面表现类似。这段代码仍然有一些地方导致内存泄漏
帮忙
更新
我刚刚尝试注释掉f.write(buf.getvalue()),虽然它显然没有创建包含任何内容的blobstore项,但它最终完成了对所有事件实体的处理。我是否遗漏了某些内容,或者f.write()是否泄漏内存或缓冲所有内容直到finalize()?当调用f.write(buf.getvalue())
时,您要求StringIO
将其自身转换为单个内存对象并传递该对象。那会很贵的
尝试buf.seek(0)
,它将倒回流的开头,只需传递f.write(buf)
StringIO
是一个类似文件的对象,f.write
应该能够以流的形式读取它
看看,从文档或代码中不清楚文件\u服务\u pb.AppendRequest
是否可以处理StringIO。试试看。什么是事件
?一个AppEngine对象?原始版本做了什么?不知道它做了什么就知道它“呕吐”是没有帮助的。谢谢。我对问题进行了编辑,以提供更清晰的信息。有用的观察结果,我将加以利用。但是,buf.getvalue()
可能需要临时复制字符串,我同意这是低效的,但它不应该泄漏。它使它在内存耗尽之前循环20多次。如果我切换,它可能会使它循环一个额外的时间,因为峰值内存较低,但它不应该解决整个问题。事实上。您的“文件”
”也可能存储了自己的缓冲区。目前无法检查,但请尝试在GAE文件对象上查找flush
方法。