0

I am trying to create thumbnails for photos that are in my s3 bucket, using lambda function. I have added the lambda function code inside the code editor in lambda, and have separately compiled and packaged the pillow library using my local machine on macOS. it didn't work and error each time was the PIL cannot be found, I think it was because lambda OS requires Amazon linux.

Then, I spun an ec2 instance with Amazon linux 2 AMI, compiled and zipped the pillow library inside the ec2 instance.

Then downloaded the zipped file to my local machine. As a final step created a lambda layer, and uploaded the zipped file, and added the layer to my lambda function. This should have solved the issue, but it still didn't.

Error message after testing the lambda function:

Test Event Name test2

Response
{
  "errorMessage": "Unable to import module 'lambda_function': No module named 'PIL'",
  "errorType": "Runtime.ImportModuleError",
  "requestId": "c817cf4b-ba94-4fda-bf39-fefce592d42e",
  "stackTrace": []
}

Function Logs
START RequestId: c817cf4b-ba94-4fda-bf39-fefce592d42e Version: $LATEST
[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'PIL'
Traceback (most recent call last):END RequestId: c817cf4b-ba94-4fda-bf39-fefce592d42e
REPORT RequestId: c817cf4b-ba94-4fda-bf39-fefce592d42e  Duration: 1.96 ms   Billed Duration: 2 ms   Memory Size: 128 MB Max Memory Used: 53 MB  Init Duration: 261.59 ms

Lambda code:

import sys
import urllib.request
from PIL import Image


s3_client = boto3.client('s3')
 
def resize_image(image_path, resized_path):
    with Image.open(image_path) as img:
        img.thumbnail((500, 500))
        img.save(resized_path)

def lambda_handler(event, context):
    for record in event['Records']:
        bucket = record['s3']['bucket']['name']
        key = urllib.parse.unquote_plus(record['s3']['object']['key'], encoding='utf-8')

        if "/raw-media/" not in key:
            continue

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

        s3_client.download_file(bucket, key, download_path)
        resize_image(download_path, upload_path)

        # Extract the username and replace "raw-media" with "thumbnails" for the upload
        user_folder = key.split("/")[0]  # get the username folder
        thumbnail_key = f"{user_folder}/thumbnails/{tmpkey}"
        
        s3_client.upload_file(upload_path, bucket, thumbnail_key)

Any suggestion please, how to solve this? I also have tried a lambda function for resizing photos, and I have got the same errors. I even tried docker, but each time there were errors.

1

1 Answer 1

0

The reason Pillow couldn't be imported in Lambda is because you must first create a lambda layer with the package to import. You can find a one-click script to generate a layer -> push to AWS here.

The AWS Docs on Creating a Python Lambda Layer are also helpful.

Sign up to request clarification or add additional context in comments.

2 Comments

Although it's quite late responding to you now, but @John Rotenstein thank you for your help, much appreciated!
If this answer helped you, please mark it as correct as per the Stack Overflow guidelines :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.