PIL and python static typing

Viewed 5514

I have a function argument which can accept several types for an image:

def somefunc(img: Union[np.array, Image, Path, str]):

The PIL Image in this case throws the following exception:

TypeError: Union[arg, ...]: each arg must be a type. Got <module 'PIL.Image' from ...

Which makes sense after inspecting an image object further:

print(type(Image.open('someimage.tiff')))
>>> <class 'PIL.TiffImagePlugin.TiffImageFile'>

How would I go about specifying a generalized type for a PIL image? It being from a file and it's format should be irrelevant.

2 Answers

I don't have a IDE handy, but the error you're getting:

. . . Got <module 'PIL.Image'

Suggests that you're attempting to use the module itself as a type when you mean to refer to the Image object contained within the module.

I'm guessing you have an import like

from PIL import Image

Which makes Image refer to the module, not the object.

You want something like

from PIL.Image import Image

So that the object itself is imported.

Note though, now Image refers to the object. You may need to do something like this if you want to refer to both the object and module within the same file:

from PIL import Image as img
from PIL.Image import Image

Now the module is aliased as img.

Similar to the other answers, you could do def somefunc(img: Union[np.array, Image.Image, Path, str]): to call the module's object directly. Tested in python 3.9.

from PIL import Image

img = Image.open('some_path.png')
print(type(img))  # <class 'PIL.PngImagePlugin.PngImageFile'>
def to_gray(img:Image.Image):
    return img.convert("L")
img = to_gray(img)
print(type(img))  # <class 'PIL.Image.Image'>

The type changes normally with .convert("L")

Related