AWS Lambda - Python - S3 to Drive Service работает, проблема с большими файлами - PullRequest
1 голос
/ 22 апреля 2020

Итак, я создаю сервис, который копирует файлы из S3 Bucket в папку Drive. Он запускает лямбду, когда объект создается в папке S3 Bucket /. Я беру файл (большой TXT-файл), копирую его содержимое «локально», чтобы иметь возможность загрузить его на диск через его API. Программа работает отлично, за исключением больших файлов. У меня заканчивается память:

     [Errno 28] No space left on device: OSError
     Traceback (most recent call last):
       File "/var/task/lambda_function.py", line 67, in lambda_handler
         raise e
       File "/var/task/lambda_function.py", line 56, in lambda_handler
         f.write(chunk[0:last_newline+1].decode('utf-8'))
     OSError: [Errno 28] No space left on device

Вот код, который генерирует эту проблему, размер файла около 270 Мб. Тестирование запуска Lambda с настроенной памятью 2 ГБ.

obj = s3.get_object(Bucket = bucket,Key=key) #Getting the object that triggered the Lambda
fullpath="/tmp/"+key #To create a "local file" keeping its original name
os.chdir('/tmp')
f= open(fullpath,"w+") #Open the file to start writing in it.
body = obj['Body']
chunk_size = 1000000 * 10 #Reading it in chunks of ~10MB
newline = '\n'.encode()   
partial_chunk = b''
while (True):
    chunk = partial_chunk + body.read(chunk_size)
    if chunk == b'':
        break
    last_newline = chunk.rfind(newline)
    f.write(chunk[0:last_newline+1].decode('utf-8')) #Writing to the file (GETTING OUT OF MEMORY HERE)
    f.flush()
    # keep the partial line you've read here
    partial_chunk = chunk[last_newline+1:]
f.close() 
upload(parent,filename,key,fullpath)

И для загрузки я делаю:

 upload():
 ...
 drive_service = build('drive', 'v3', credentials=credenciales)
 media_body1 = MediaFileUpload(fullpath, resumable=True,chunksize=1024 * 1024 * 5) #Using 5MB chunks
 body1={'name':fullpath,'parents':[parent]}#,'media_body':content}
 Filesubido = drive_service.files().create(body=body1, media_body=media_body1, supportsAllDrives='True')
 response = None
 while response is None:
     time.sleep(5)
     status, response = Filesubido.next_chunk()
     if status:
         print ("Uploaded "+ str(int(status.progress() * 100)))
print ("Upload Complete!")

Вещи, которые я пробовал:

  • Расшифровывая тело файла прямо в память, скажем, content=obj['Body'].read().decode('utf-8') У лямбды не хватает памяти, поэтому я читаю ее порциями и сохраняю в файл вот так, но теперь у меня заканчивается «хранилище» (500 МБ макс., но размер файла составляет 270 МБ).

Вопросы:

  • Можно ли загрузить файл в API накопителя БЕЗ сохранения файла локально на /tmp? * 1021 Lambda *
  • Любые другие идеи о том, как обработать файл, чтобы иметь возможность загрузить его с тем, что у меня есть?

Ура!

1 Ответ

0 голосов
/ 22 апреля 2020

AWS Функции лямбды могут использовать 512 МБ свободного места на диске /tmp. Когда лямбда-функция закончила использовать временный файл, она должна удалить этот файл, чтобы освободить место для всех будущих исполнений функций, которые повторно используют тот же контейнер Lambda.

Пока ваши файлы не превышают 512 МБ , тогда это должно работать нормально для вас.

Если они имеют размер более 512 МБ, вам нужно будет прочитать фрагменты данных из Amazon S3 и загрузить их по назначению, просматривая все фрагменты. Это делает его более сложным как для чтения, так и для записи.

В качестве альтернативы, вы можете использовать другой вычислительный сервис, такой как Amazon EC2 или Fargate.

...