Python 3.15 support
What did you do?
Installed a package (matplotlib) with a Pillow dependency on Python 3.15
What did you expect to happen?
Build on CI
edit I think what actually this is due to is 3.15 wheels not being available for pillow
What actually happened?
Details
Downloaded opencv-python
Building pillow==12.0.0
Building scipy==1.16.3
Building numpy==2.3.5
× Failed to build `pillow==12.0.0`
├─▶ The build backend returned an error
╰─▶ Call to `backend.build_wheel` failed (exit status: 1)
[stdout]
running bdist_wheel
running build
running build_py
creating build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_binary.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/XVThumbImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/PixarImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/GribStubImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageStat.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/QoiImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageDraw.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ContainerIO.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_deprecate.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageEnhance.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_util.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_version.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/features.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/TgaImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/JpegPresets.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageWin.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/PcdImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/PngImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/BlpImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/AvifImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/EpsImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/GbrImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/PpmImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/TiffImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/McIdasImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageFont.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/JpegImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageText.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/PaletteFile.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/WebPImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/SunImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageDraw2.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/Jpeg2KImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/PsdImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageMode.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageTransform.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/report.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/FpxImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/GimpGradientFile.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/WmfImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/PcxImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/WalImageFile.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/BdfFontFile.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageColor.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/DcxImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/IcnsImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageSequence.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageFilter.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageMath.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/IptcImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/GdImageFile.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/MpoImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/Hdf5StubImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageTk.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageMorph.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/PalmImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/XpmImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/XbmImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/FontFile.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImagePath.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/FitsImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/Image.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/CurImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/BufrStubImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_typing.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageShow.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageOps.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/TiffTags.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/FtexImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ExifTags.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImagePalette.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/PdfImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImtImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/FliImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/MpegImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageFile.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageCms.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageGrab.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/PdfParser.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/DdsImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/GifImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/MspImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/PSDraw.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/__main__.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_tkinter_finder.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageChops.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/PcfFontFile.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/IcoImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/__init__.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/ImageQt.py -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/SpiderImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/BmpImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/MicImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/SgiImagePlugin.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/GimpPaletteFile.py ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/TarIO.py -> build/lib.linux-x86_64-cpython-315/PIL
running egg_info
writing src/pillow.egg-info/PKG-INFO
writing dependency_links to src/pillow.egg-info/dependency_links.txt
writing requirements to src/pillow.egg-info/requires.txt
writing top-level names to src/pillow.egg-info/top_level.txt
reading manifest file 'src/pillow.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
adding license file 'LICENSE'
writing manifest file 'src/pillow.egg-info/SOURCES.txt'
copying src/PIL/_avif.pyi -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_imaging.pyi -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_imagingcms.pyi ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_imagingft.pyi -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_imagingmath.pyi ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_imagingmorph.pyi ->
build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_imagingtk.pyi -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/_webp.pyi -> build/lib.linux-x86_64-cpython-315/PIL
copying src/PIL/py.typed -> build/lib.linux-x86_64-cpython-315/PIL
running build_clib
building 'pil_imaging_mode' library
creating build/temp.linux-x86_64-cpython-315/src/libImaging
cc -pthread -fno-strict-overflow -Wsign-compare -Wunreachable-code
-DNDEBUG -g -O3 -Wall -O3 -fPIC -fPIC -c src/libImaging/Mode.c -o
build/temp.linux-x86_64-cpython-315/src/libImaging/Mode.o
ar rcs build/temp.linux-x86_64-cpython-315/libpil_imaging_mode.a
build/temp.linux-x86_64-cpython-315/src/libImaging/Mode.o
running build_ext
[stderr]
warning: no files found matching '*.c'
warning: no files found matching '*.h'
warning: no files found matching '*.sh'
warning: no files found matching '*.txt'
warning: no files found matching '.flake8'
warning: no previously-included files found matching '.clang-format'
warning: no previously-included files found matching '.coveragerc'
warning: no previously-included files found matching '.editorconfig'
warning: no previously-included files found matching '.readthedocs.yml'
warning: no previously-included files found matching 'codecov.yml'
warning: no previously-included files found matching 'renovate.json'
warning: no previously-included files found matching
'Tests/images/README.md'
warning: no previously-included files found matching
'Tests/images/crash*.tif'
warning: no previously-included files found matching
'Tests/images/string_dimension.tiff'
warning: no previously-included files matching '.git*' found anywhere
in distribution
warning: no previously-included files matching '*.so' found anywhere
in distribution
no previously-included directories found matching '.ci'
no previously-included directories found matching 'wheels'
no previously-included directories found matching 'winbuild/build'
no previously-included directories found matching 'winbuild/depends'
no previously-included directories found matching 'Tests/errors'
no previously-included directories found matching
'Tests/images/jpeg2000'
no previously-included directories found matching 'Tests/images/msp'
no previously-included directories found matching 'Tests/images/picins'
no previously-included directories found matching
'Tests/images/sunraster'
no previously-included directories found matching 'Tests/test-images'
The headers or library files could not be found for jpeg,
a required dependency when compiling Pillow from source.
Please see the install instructions at:
https://pillow.readthedocs.io/en/latest/installation/basic-installation.html
Traceback (most recent call last):
File "<string>", line 1101, in <module>
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/__init__.py",
line 115, in setup
return distutils.core.setup(**attrs)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/_distutils/core.py",
line 186, in setup
return run_commands(dist)
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/_distutils/core.py",
line 202, in run_commands
dist.run_commands()
~~~~~~~~~~~~~~~~~^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/_distutils/dist.py",
line 1002, in run_commands
self.run_command(cmd)
~~~~~~~~~~~~~~~~^^^^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/dist.py",
line 1102, in run_command
super().run_command(command)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/_distutils/dist.py",
line 1021, in run_command
cmd_obj.run()
~~~~~~~~~~~^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/command/bdist_wheel.py",
line 370, in run
self.run_command("build")
~~~~~~~~~~~~~~~~^^^^^^^^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/_distutils/cmd.py",
line 357, in run_command
self.distribution.run_command(command)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/dist.py",
line 1102, in run_command
super().run_command(command)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/_distutils/dist.py",
line 1021, in run_command
cmd_obj.run()
~~~~~~~~~~~^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/_distutils/command/build.py",
line 135, in run
self.run_command(cmd_name)
~~~~~~~~~~~~~~~~^^^^^^^^^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/_distutils/cmd.py",
line 357, in run_command
self.distribution.run_command(command)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/dist.py",
line 1102, in run_command
super().run_command(command)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/_distutils/dist.py",
line 1021, in run_command
cmd_obj.run()
~~~~~~~~~~~^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/command/build_ext.py",
line 96, in run
_build_ext.run(self)
~~~~~~~~~~~~~~^^^^^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/_distutils/command/build_ext.py",
line 368, in run
self.build_extensions()
~~~~~~~~~~~~~~~~~~~~~^^
File "<string>", line 897, in build_extensions
RequiredDependencyException: jpeg
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<string>", line 11, in <module>
wheel_filename =
backend.build_wheel("/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpkdWXj3",
{}, None)
File
"/home/runner/work/_temp/setup-uv-cache/sdists-v9/pypi/pillow/12.0.0/URQSc5nsInBdZ16w7Yiay/src/_custom_build/backend.py",
line 26, in build_wheel
return super().build_wheel(wheel_directory, config_settings,
metadata_directory)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/build_meta.py",
line 432, in build_wheel
return _build(['bdist_wheel'])
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/build_meta.py",
line 423, in _build
return self._build_with_temp_dir(
~~~~~~~~~~~~~~~~~~~~~~~~~^
cmd,
^^^^
...<3 lines>...
self._arbitrary_args(config_settings),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/build_meta.py",
line 404, in _build_with_temp_dir
self.run_setup()
~~~~~~~~~~~~~~^^
File
"/home/runner/work/_temp/setup-uv-cache/sdists-v9/pypi/pillow/12.0.0/URQSc5nsInBdZ16w7Yiay/src/_custom_build/backend.py",
line 20, in run_setup
return super().run_setup(setup_script)
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
File
"/home/runner/work/_temp/setup-uv-cache/builds-v0/.tmpk4DpPr/lib/python3.15/site-packages/setuptools/build_meta.py",
line 317, in run_setup
exec(code, locals())
~~~~^^^^^^^^^^^^^^^^
File "<string>", line 1118, in <module>
RequiredDependencyException:
The headers or library files could not be found for jpeg,
a required dependency when compiling Pillow from source.
Please see the install instructions at:
https://pillow.readthedocs.io/en/latest/installation/basic-installation.html
hint: This usually indicates a problem with the package or the build
environment.
help: `pillow` (v12.0.0) was included because `page-dewarp` (v0.2.0) depends
on `matplotlib` (v3.10.7) which depends on `pillow`
Error: Process completed with exit code 1.
What are your OS, Python and Pillow versions?
- OS: Ubuntu
- Python: 3.15.0a2
- Pillow: 12.0
3.15?!
Yes! It is available for testing, I think this issue should probably have been titled “please may we have Python 3.15 wheels?” 🙂
The real issue is not that it won’t build, but that my CI can only be expected to use it as a wheel, and it looks like there are only up to 3.14 yet. Not sure if that’s something Pillow team have planned yet?
It’s in pre-release at 3.15.0a2 so far, I think I read they plan to do 7.
We'll get there, especially since @hugovk is the release manager, but I'm not sure when. At a glance it just looked like missing deps, the same as you'd encounter with any other version.
Yes sorry for the title ! 👍
edit FWIW yes it built just fine with the following headers
- name: Install Pillow build dependencies (Python 3.15+)
if: startsWith(matrix.python-version, '3.15')
run: sudo apt-get update && sudo apt-get install -y libjpeg-dev zlib1g-dev libtiff-dev libfreetype6-dev
Ok, cool, so you've figured out how to build it from source.
As for when we will distribute wheels, we use https://github.com/pypa/cibuildwheel as part of our process. Their habit is to wait for the beta release of the next Python version, which is scheduled for May 5th. Our next release after that will be Pillow 12.3.0 on July 1st.
Official Pillow support for Python 3.15 will not land until our release of Pillow 13.0.0 on October 15, after the final version of Python 3.15 becomes available.
I've opened https://github.com/python-pillow/Pillow/pull/9331 to start testing 3.15.
Pillow 12.2 will be released in April.
When cibuildwheel adds 3.15 support in May, we could also consider creating 3.15 wheels for Pillow 12.2 and uploading them to the existing release, so people don't need to wait until July.