May 05, 2021
deploying PIL to lambda
So, I've been building some serverless functions. The serverless model on AWS works great:
- Create a resource and method on API Gateway
- Use a LAMBDA PROXY as the Integration type
- Deploy code to lambda and dependencies as a lambda layer
- Use APIGW Stage variables and lambda alias to aid in CD
- Access your method via the endpoint after deploying the gateway
I ran into a minor issue while trying to deploy PIL (the imaging Python library) as a lambda layer. I was met with this error multiple times:
Unable to import module 'lambda_function': cannot import name '_imaging' from 'PIL'
The Solution
pip freeze > requirements.txt
mkdir python
docker run -v "$PWD":/var/task "public.ecr.aws/sam/build-python3.7" /bin/sh -c "pip install -r requirements.txt -t python/; exit"
zip -r mypythonlibs.zip python > /dev/null
aws lambda publish-layer-version --layer-name LAYER_NAME --zip-file fileb://mypythonlibs.zip --compatible-runtimes "python3.7"
aws lambda update-function-configuration --layers arn:aws:lambda:ap-southeast-1:ACCOUNT_ID:layer:PIL-layer:LAYER_VERSION --function-name FUNCTION_NAME
Find other images from AWS SAM here
The Why
If you query into the python
folder, you can see:
python
|- PIL
|- Pillow-8.2.0.dist-info
|- Pillow.libs
Aha, the folder Pillow.libs was missing when I uploaded the dependencies to the lambda layer from my virtualenv lib for the first time.
A lot of solutions on the net suggested something like creating an EC2 linux and building PIL from there.
The main problem is that installing Pillow from our local computer and uploading the resulting bulid is different from the one that the lambda runtime will use. It is missing all the support files needed to run and compile.
I like the docker method! It is fast.