No module named ‘_cffi_backend'”
Issue In Local Development Environment
When building serverless applications, often time we use SAM to deploy and develop lambda functions in the local environment. Most of our engineers in the firm using macOS or Windows, which is a different runtime environment as Lambda runtime environment on AWS. Just take one of my examples, I was trying to encrypt/decrypt documents through python cryptography The program can run perfectly on my local windows environment, then I deployed everything from SAM. When I ran the lambda function on the AWS console, I was getting the following error.
{
"errorMessage": "Unable to import module 'python_handler': No module named '_cffi_backend'",
"errorType": "Runtime.ImportModuleError"
}
Native Library Package Incompatibility
At first, I thought it was an import issue, so I try to package it again. The issue was still present.
After doing research on the internet, I found a StackOverflow discussion and a technical blog. I found it could be a packaging issue since AWS Lambda is running on a Linux environment, but I packaged it through windows or MacOs. The issue could also surge when testing the code on lambda container through sam invoke or other equivalent methods.
Root Cause of Lambda Incompatibility
After I dug deep into the problem, it was the package generated on the Windows platform with the pip command. The libraries, native to OS, were compiled for the windows or Mac operation system.
In my case, cryptography is a platform-specific library. So, if I run my function on AWS environment, I got “Unable to import module ‘python_handler’: No module named ‘_cffi_backend'”
This problem is not only for the cryptography library but also for all python libraries written in the C language. Such as Pillow(image processing), pandas(scientific lib), sklearn(Machine learning) and etc. Because these compiled binary c libs are platform-dependent.
We could deduce that error not only occurs in Python but also in Nodejs. Because Nodejs is also a platform-dependent language.
After knowing the root cause, the solution is relatively easy.
The solutions for Lambda Incompatibility
There are at least two solutions for us.
Solution 1: Standardized building environment.
As we know the issue comes from the discrepancy between the building environment and the lambda runtime environment. So, the easiest way is to change the building environment to the same one as the running environment.
We can launch an Amazon Linux instance on the AWS EC2 platform. And then build and package our lambda code there.
In this way, the environmental discrepancy is eliminated. I believe it’s a good practice for the CI/CD process but lots of overhead for a local development environment.
Solution 2: Containerization(Docker)
As we mentioned the previous solution has lots of overhead for local development. One can simulate the environment with containerization technology. Docker is able to provide us perfectly isolated Linux environment. We could use an Amazon Linux compatible image to build and package.
Sample script
mkdir -p /tmp/python/lib/python3.7/
cp ./requirements.txt /tmp/
cd /tmp/
# this image is compatible with the lambda runtime.
docker run \
-v "$PWD":/var/task \
"lambci/lambda:build-python3.7" \
/bin/sh -c "pip install -r requirements.txt -t python/lib/python3.7/site-packages/; exit"
zip -r package.zip python > /dev/null
Mu
Solution Architect@ASCENDING