When running the code snip below within a pipenv (2018.11.26) using virtualenv (16.7.7) in a raspbian , it executes flawlessly and all the operations complete as expected.
import logging
import distutils
from PIL import Image, ImageDraw, ImageFont, ImageFile, ImageOps
from pathlib import Path
logger = logging.getLogger(__name__)
logger.root.setLevel('DEBUG')
image = Path('/home/pi/tmp/4886.jpg').expanduser()
size = (100, 200)
try:
logging.info(f'opening image: {image}')
im = Image.open(image)
im.thumbnail(size)
except (PermissionError, FileNotFoundError, OSError) as e:
logging.warning(f'could not open image file: {image}')
logging.warning(f'image error: {e}')
logging.warning(f'using empty image')
print(f'image size is: {im.size}')
output This produces the expected result
INFO:root:opening image: /home/pi/tmp/4886.jpg
image size is: (100, 90)
After packaging it with pipenv run python -m PyInstaller im_open.py
the compiled version complains DEBUG:PIL.Image:Image: failed to import JpegImagePlugin: No module named 'distutils'
output
INFO:root:opening image: /home/pi/tmp/4886.jpg
...
DEBUG:PIL.Image:Importing IptcImagePlugin
DEBUG:PIL.Image:Importing JpegImagePlugin
DEBUG:PIL.Image:Image: failed to import JpegImagePlugin: No module named 'distutils'
DEBUG:PIL.Image:Importing Jpeg2KImagePlugin
DEBUG:PIL.Image:Importing McIdasImagePlugin
DEBUG:PIL.Image:Importing MicImagePlugin
DEBUG:PIL.Image:Image: failed to import MicImagePlugin: No module named 'olefile'
DEBUG:PIL.Image:Importing MpegImagePlugin
DEBUG:PIL.Image:Importing MpoImagePlugin
DEBUG:PIL.Image:Image: failed to import MpoImagePlugin: No module named 'distutils'
DEBUG:PIL.Image:Importing MspImagePlugin
DEBUG:PIL.Image:Importing PalmImagePlugin
DEBUG:PIL.Image:Importing PcdImagePlugin
...
WARNING:root:could not open image file: /home/pi/tmp/4886.jpg
WARNING:root:image error: cannot identify image file '/home/pi/tmp/4886.jpg'
WARNING:root:using empty image
Traceback (most recent call last):
File "im_open.py", line 69, in <module>
print(f'image size is: {im.size}')
NameError: name 'im' is not defined
I've tried the following:
hiddeimports=['distutils']
Relevant research
There is a workaround for this issue in another bug report. The following method appears to resolve this issue for virtualenv 16.4.0 through at least 16.7.7
pipenv install PyInstaller
pipenv open PyInstaller
and edit hooks/pre_find_module_path/hook-distutils.py
to match the patch shown below.patched pre_find_module_path/hook-distutils.py
import distutils
import os
from PyInstaller.utils.hooks import logger
def pre_find_module_path(api):
# Absolute path of the system-wide "distutils" package when run from within
# a venv or None otherwise.
distutils_dir = getattr(distutils, 'distutils_path', None)
if distutils_dir is not None:
# workaround for https://github.com/pyinstaller/pyinstaller/issues/4064
if distutils_dir.endswith('__init__.py'):
distutils_dir = os.path.dirname(distutils_dir)
# end workaround patch
# Find this package in its parent directory.
api.search_dirs = [os.path.dirname(distutils_dir)]
logger.info('distutils: retargeting to non-venv dir %r' % distutils_dir)