2016-12-20 28 views
0

私は元のバケットの 'root'のイメージでうまく動作している私の最初のAWS Lambdaイメージオプティマイザスクリプトを作成しています。AWS Lambda Pythonのフォルダ処理

私は3つのバケツを持っています。 'mybucket'には、サイズを変更したいオリジナルの画像が保存されます。私はそれを見ているpythonラムダ関数を持っている 'mybucket-photos'にそれらをコピーすることに決めました。 Lammbda関数は入力された写真を最適化し、 'mybucket-photosresized'に保存します。

しかし、mybucketの写真にmybucketの内容をコピーしようとすると、私はpythonスクリプトファイルの処理とキーの 'サブフォルダ'部分に関して失敗します。

例失敗:

そのようなファイルまたはディレクトリ:「/ tmpに/ 91979758-51b3-44df-b2b1-d9eeddeb0802saddles /親指/ 27dfahl/16-5-DK-馬場馬術サドルの売却/ saddle_photo02_300 .3a38de5F ':IOError

私の疑問は、スラッシュを含むフォルダ名が問題を引き起こしているということです。私は 'フォルダ'がキーの一部であることを理解しています。

ちなみに、作成中のレコード、バケツ、キーに関して、ハンドラメソッドが何をしているのか分かりません。私の素朴な本能は、何とか置き換えて、それを元に戻すことです。

のpythonは次のとおりです。

from __future__ import print_function 
import boto3 
import os 
import sys 
import uuid 
from PIL import Image 
import PIL.Image 

s3_client = boto3.client('s3') 

def resize_image(image_path, resized_path): 
    with Image.open(image_path) as image: 
     image.save(resized_path,optimize=True) 

def handler(event, context): 
    for record in event['Records']: 
     bucket = record['s3']['bucket']['name'] 
     key = record['s3']['object']['key'] 
     download_path = '/tmp/{}{}'.format(uuid.uuid4(), key) 
     upload_path = '/tmp/resized-{}'.format(key) 

     s3_client.download_file(bucket, key, download_path) 
     resize_image(download_path, upload_path) 
     s3_client.upload_file(upload_path, '{}resized'.format(bucket), key) 

いただきました。このスクリプトで「フォルダ」を処理するための最良の方法は?

答えて

0

私の元のコードはawsによって提供されました。私は、ファイルシステムにファイルを保存することを選択したと思う。最適化などの方法でイメージを保存する必要があるからだ。

私は元のコードに固執し、正規表現でパスとファイル名を取り除くことに決めました。それは私の必要性のために十分にうまくいくようです。私は、いくつかの問題を、拡張機能などがないファイルでバックグラウンドでいくつか確認しました。

from __future__ import print_function 
import boto3 
import os 
import sys 
import uuid 
from PIL import Image 
import PIL.Image 
import re 

s3_client = boto3.client('s3') 

def resize_image(image_path, resized_path): 
    with Image.open(image_path) as image: 
     image.save(resized_path,optimize=True) 

def handler(event, context): 
    for record in event['Records']: 
     bucket = record['s3']['bucket']['name'] 
     key = record['s3']['object']['key'] 

     file_name_pattern = re.match(r'(.*?([^/]+)/?)$',str(key)) 
     file_name = file_name_pattern.group(2) 
     path_without_name = file_name_pattern.group(1) 

     download_path = '/tmp/{}{}'.format(uuid.uuid4(), file_name) 
     upload_path = '/tmp/resized-{}'.format(file_name) 

     s3_client.download_file(bucket, key, download_path) 
     resize_image(download_path, upload_path) 
     s3_client.upload_file(upload_path, '{}resized'.format(bucket), str(key)) 
2

S3からLambda機能を実行しているマシンのローカルフォルダにオブジェクトをダウンロードしています。そのマシンは(ほぼ確実に)Linuxファイルシステムを持っています。通常、そのようなフォルダが存在しない限り、そのようなファイルシステム上のフォルダにファイルを書き込むことはできません。ダウンロードされたオブジェクトを保持するフォルダを作成しようとするコードがコード内に表示されません。

また、ダウンロードしたオブジェクトのキーをダウンロードフォルダ名にバインドすることで、これをさらに複雑にしました。だから、

、単純に/ tmp /またはへの/ tmp /ダウンロードにダウンロード/(あなたは事前に作成している)か、事前にしなければならない、その場合にはS3オブジェクトキー名が、を含むフォルダにダウンロードし続けるのいずれか関連するフォルダ階層を作成します。

1

通常のプラットフォームでのコーディングと同様に、オブジェクトがRAMより大きくなければファイルシステムを使用する必要はなく、代わりにメモリオブジェクトでスワップします。とにかくそれを処理するのに十分なメモリ(RAM +スワップ)が必要です。これははるかに高速でエラーの発生が少ない。

PILのImage.open()がファイルオブジェクトをとり、botoのs3_client.get_object()['Body']がメモリ内ファイルオブジェクトを返します。残念ながら、botoオブジェクトはseek()をサポートしていないため、うまく動作することはありません。あなたはあなたのために一時ファイルを作成するために、Pythonのtempfile.TemporaryFileを使用し、ファイルシステムを使用する必要がある場合

s3_object = s3_client.get_object(Bucket=bucket, Key=key) 
file_obj = s3_object['Body'] 
file_contents = file_obj.read() 

pil_image = Image.fromstring(file_contents) 

:代わりに、レスポンスボディからバイトでImage.fromstring()を使用しています。

+0

私は最終的なコードに追加しました。 –

関連する問題