'Python Layer Image Failing: "Unable to import module 'lambda_function': cannot import name '_imaging' from 'PIL'"

I'm simply trying to be able to use PIL in my Python 3.8 Lambda.

I'm trying the following steps:

  1. Based on this repo: https://github.com/hidekuma/lambda-layers-for-python-runtime
cd /mydir 
git clone https://github.com/hidekuma/lambda-layers-for-python-runtime.git 
cd lambda-layers-for-python-runtime 
mkdir dist 
docker-compose up --build
  1. Based on this guidance: https://www.splunk.com/en_us/blog/cloud/sharing-code-dependencies-with-aws-lambda-layers.html
aws lambda publish-layer-version --layer-name ImageStorageDependencies
    --description "A Python 3.8 runtime with PIL and boto3 installed." --license-info "MIT" --zip-file fileb://output.zip --compatible-runtimes python3.7 python3.8 --region us-east-2

I then choose my layer in the Lamda configuration, but when I run this code:

import json
import boto3
import io
from PIL import Image


def lambda_handler(event, context): 
    #etc

...I get the error:

[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': cannot import name '_imaging' from 'PIL' 

Where exactly am I going wrong?!?



Solution 1:[1]

Just to clarify, regarding your comment above, Pillow is just a repackaged, updated version of PIL because the original maintainers of PIL stopped working on it a long time ago. When you pip install Pillow, you still import it as PIL. In this case they are the same thing.

To answer your question, the the Pillow install directions mention:

Pillow >= 2.1.0 no longer supports import _imaging. Please use from PIL.Image import core as _imaging instead.

I'm not sure where your code imports _imaging, so I think you have a few options:

  1. Use an older version of Pillow (pre 2.1.0)
  2. Find where you are importing _imaging and replace it with the updated from PIL.Image import core as _imaging
  3. Update to the current version of Pillow (see my update below)

There is a fourth option which is redirecting the import manually, inspired by this question. I would only do this if you can't do one of the first three. Put this somewhere in your code that gets run before you do the import that is breaking things. You may have to tweak this slightly to make it work:

from PIL.Image import core as _imaging
import sys
sys.modules['PIL._imaging'] = _imaging

A later from PIL import _imaging should now really import the new core.

Update:

Updating Pillow may also solve the problem. In 7.2.0, I can import _imaging in the old way:

>>> import PIL
>>> from PIL import _imaging
>>> print(PIL.__version__)
7.2.0
>>> print(_imaging)
<module 'PIL._imaging' from '...\\lib\\site-packages\\PIL\\_imaging.cp37-win_amd64.pyd'>

Solution 2:[2]

I found this answer on the internet:

ImportError: cannot import name _imaging, It can happen if you have PIL installed, then install Pillow on top of it. Go to /usr/local/lib/python2. 7/dist-packages/ and delete anything with "PIL" in the name (including directories). Then re-install Pillow. When I run from PIL import Image or from PIL import Image etc, I get the error: ImportError: cannot import name 'imaging' from 'PIL' (C:\Users\Pruthvi\AppData\Local\Programs\Python\Python38-32\Lib\site-packages\PIL_init.py) So odd since these same exact commands were working fine yesterday when I was exploring the PIL and pillow modules.

I believe that this issue is related to Pillow library.

Solution 3:[3]

I had this issue with an AWS Lambda. Pillow would load for one of my Lambdas, but not another. I was able to fix it by making sure the Lambda was running on the Architecture "x86_64", not "arm64" in the AWS Lambda Runtime Settings.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Raul Barreto
Solution 3 Bktrout47