在Python 2.5中将Google App Engine blobstore写入文件的正确方法是什么?

时间:2012-02-09 12:21:13

标签: python google-app-engine

当我尝试对Google App Engine blobstore进行简单写入时,我目前超出了内存限制。编写此代码以使其不泄漏内存的正确方法是什么?

from __future__ import with_statement
from google.appengine.api import files
from google.appengine.api import blobstore
def files_test(limit):
file_name = files.blobstore.create(mime_type='application/octet-stream') 
   try:
     with files.open(file_name, 'a') as f:
       for x in range(limit):
         f.write("Testing \n")

   finally:
     files.finalize(file_name)
     return files.blobstore.get_blob_key(file_name)

files_test(4000)产生错误:

在为27个请求提供服务后,超出了157.578 MB的软私有内存限制

4 个答案:

答案 0 :(得分:3)

不幸的是,python的垃圾收集器并不完美。你做的每一次写操作都会创建许多小对象(通过协议缓冲区创建),由于某种原因,这些小对象不是由python动态收集的。我发现在mapreduce库中我必须要做

import gc
gc.collect()

不时让垃圾收集者高兴。

答案 1 :(得分:0)

由于它是Python 2.5,xrange应该优于range,不是吗?

答案 2 :(得分:0)

您应该立即写入所有数据以避免问题并加快速度 - 优化它 - 它应该停止问题但不能解决错误 - > http://docs.python.org/library/stringio.html。考虑到file.write可能不是简单的写入,但是对RPC API的请求设置很慢 - 请参阅SDK代码 - 避免多次调用/缓冲。

如此少量的数据4000 * 9不应该出现 - 它看起来像Google API中的错误 - 只需报告http://code.google.com/p/googleappengine/issues/list?can=2&q=&sort=-id&colspec=ID%20Type%20Component%20Status%20Stars%20Summary%20Language%20Priority%20Owner%20Log

考虑将'create'标记为实验http://code.google.com/intl/pl/appengine/docs/python/blobstore/overview.html#Writing_Files_to_the_Blobstore

修复也最终确定错误 - 如果异常,则无法完成无效文件或返回结果!

import StringIO

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

def files_test(limit):
    output = StringIO.StringIO()

    # workaround!
    for x in range(limit):
        output.write("Testing \n")

    file_name = files.blobstore.create(mime_type='application/octet-stream') 
    try:
        with files.open(file_name, 'a') as f:
            # workaround!
            f.write(output.getvalue())

    finally:
        output.close()

    files.finalize(file_name)           
    return files.blobstore.get_blob_key(file_name)

答案 3 :(得分:0)

也许我错了,但我很确定write()的调用次数可能就是问题所在。 我认为这是问题,因为当我尝试保存用户上传的文件时,我遇到了类似的问题。

对我而言,这导致了问题:

with files.open(file_name, 'a') as f:
    for chunk in read_in_chunks(data):
        f.write(chunk)    

对我来说,当我将块大小更改为1Mb而不是1Kb时,问题就消失了。