Typing stubs for Pillow
types-Pillow is a PEP 561 type stub package that provides external type annotations for the Pillow library. It enables static type checkers like mypy, pyright, and PyCharm to perform type checking on code that uses Pillow. This package specifically targets Pillow versions up to 10.2.x. Pillow versions 10.3.0 and newer now include their type annotations directly within the library, making this stub package unnecessary for those versions.
Warnings
- breaking Pillow versions 10.3.0 and newer include their type annotations directly within the Pillow package itself (via `py.typed`). If you are using Pillow 10.3.0 or a later version, you MUST uninstall `types-Pillow` to avoid duplicate type definitions and potential type-checking conflicts.
- gotcha The version of `types-Pillow` should ideally match the major.minor version of your installed `Pillow` library to ensure accurate type checking. For example, `types-Pillow==10.2.*` provides stubs for `Pillow==10.2.*`. Mismatched versions can lead to incorrect type hints or type-checking errors.
- gotcha In `Pillow > 9.1.0`, image filter constants (like `PIL.Image.LANCZOS`) were deprecated in favor of the `PIL.Image.Resampling` enum (e.g., `PIL.Image.Resampling.LANCZOS`). If you're using a newer `Pillow` (and `types-Pillow` that reflects this change) but your code still uses the old constants, type checkers will report errors.
Install
-
pip install types-pillow
Imports
- Image
from PIL import Image
Quickstart
from PIL import Image
from typing import TYPE_CHECKING
import os
# The 'types-pillow' package provides type hints for Pillow
# You don't directly import from types_pillow for usage; it's picked up by type checkers.
def process_image(img_path: str) -> Image.Image:
"""Opens an image, converts it to grayscale, and returns it."""
try:
with Image.open(img_path) as img:
# Type checkers will use the stubs provided by types-pillow
grayscale_img: Image.Image = img.convert("L")
return grayscale_img
except FileNotFoundError:
print(f"Error: Image at {img_path} not found.")
# In a real application, you might raise an error or return a default image.
# For demonstration, we'll return a new blank image.
return Image.new("L", (1, 1))
if __name__ == "__main__":
# Create a dummy image for the example if it doesn't exist
dummy_image_path = "test_image.jpg"
try:
Image.new("RGB", (100, 100), color='red').save(dummy_image_path)
except Exception:
pass # Ignore if it fails, e.g., in a read-only environment
processed = process_image(dummy_image_path)
print(f"Processed image mode: {processed.mode}, size: {processed.size}")
# processed.show() # Uncomment to display the image (might open an external viewer)
# Clean up dummy image
if os.path.exists(dummy_image_path):
os.remove(dummy_image_path)