2012-02-09 2 views
2

В настоящее время я превысил ограничение на мягкую память, когда я пытаюсь выполнить простые записи в блоб-магазине Google App Engine. Каков правильный способ написать этот код, чтобы он не просачивал память?Каков правильный способ записи в blobstore Google App Engine в виде файла в Python 2.5

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) дает ошибку:

Превышен мягкий частный предел памяти с 157.578 МБ после обслуживания 27 запросов всего

+0

, для которого значение 'limit' превышает ли вы предел памяти 128 МБ? – proppy

+0

4000 обычно это сделает. – Chris

+0

Вы пытались использовать http://code.google.com/p/apptrace/? – proppy

ответ

3

К сожалению, сборщик мусора python не идеален. Каждая запись, которую вы создаете, создает множество мелких объектов (через создание буфера протокола), которые по какой-то причине не собираются на python «на лету». Я обнаружил, что в MapReduce библиотеке я должен сделать

import gc 
gc.collect() 

время от времени держать сборщика мусора счастливым.

+0

Позднее дополнение к этому вопросу: запись таких небольших строк в файл, открытый с помощью files.open(), очень неэффективен - если вы используете Appstats, Посмотрим, что каждый вызов write() является отдельным RPC. Вы должны сделать какую-то буферизацию. (В следующем ответе также упоминается.) –

0

Поскольку Python 2.5, xrange должен быть лучше, чем range, ISN Не так ли?

+3

Да, но это вряд ли объясняет предупреждение из памяти. Список из 4000 целых чисел - это что-то вроде 4000 раз 40 байт, т. Е. 160 КБ. Это может показаться много, но это падение в 128 МБ ведра ... –

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

Считают, что «создать» помечен как экспериментальный http://code.google.com/intl/pl/appengine/docs/python/blobstore/overview.html#Writing_Files_to_the_Blobstore

Fix также финализировать ошибки - не завершать недопустимый файл или возвращать результат в случае исключения!

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) 
0

Возможно, я ошибаюсь, но я уверен, что количество вызовов для write() может быть проблемой здесь. Я думаю, что это проблема, потому что у меня была аналогичная проблема, когда я пытался сохранить файл, который был загружен пользователем.

Для меня это вызывает проблемы:

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

Для меня проблема ушла, когда я изменил размер куска быть 1Mb вместо 1Кб.

Смежные вопросы