2

I've read some other answers, and they seem contradictory to what happens IRL.

Try the following:

from typing import IO
from pathlib import Path

example_path = Path(r"D:\Example.txt")
with example_path.open("r") as f:
    print(isinstance(f, IO))
with open(example_path) as f:
    print(isinstance(f, IO))

It will print:

False
False

That's baffling, because according to documentation, it seems to me that one of the very purposes of typing.IO is for type-checking an object for IO type, and this would include the use of isinstance(). Why doesn't it work? Doesn't that defeat the very purpose? What am I missing here?

1 Answer 1

2

typing.IO and its companions are for type hinting only. At runtime they are defined as abstract generic classes, and the objects returned by open() are not instances of these classes:

class IO(Generic[AnyStr]):
    @property
    @abstractmethod
    def mode(self) -> str: pass

    @property
    @abstractmethod
    def name(self) -> str: pass

    ...

In fact, the objects in question are created in C (for CPython):

>>> type(f)
<class '_io.TextIOWrapper'>
>>> type(f).__bases__
(<class '_io._TextIOBase'>,)

Theses "private" _io types actually map to corresponding io. types, which you can use with isinstance():

>>> import io
>>> isinstance(f, io.TextIOWrapper)
True
>>> isinstance(f, io.TextIOWrapper)
True

The runtime details are covered in-depth at Check if object is file-like in Python.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.