python-3.xpython-typing

Type annotations: pathlib.Path vs importlib.resources.abc.Traversable


When loading file resources that are bundled inside my distribution package, I use importlib.resources.files. When loading files from disk, I use pathlib.Path.

Sometimes I want to write a function that will take either:

from importlib.resources.abc import Traversable
from pathlib import Path

def process_file(file_to_process: Traversable | Path) -> None: ...

It feels cumbersome to annotate all file-processing functions with Traversable | Path. I could define and use my own union type, but that feels like something that Python might already have built-in that I'm missing. I only require the basic subset of both types: open / close / read / write, etc, and nothing like touching permissions or using OS-specific details.

What is the correct type to use for a file resource that can be loaded from a distribution package via importlib or from a drive via pathlib?

I'm currently using Python 3.11 but will upgrade over time, so all 3.11+ answers are welcome.


Solution

  • I believe you can just use Traversable in all cases. It looks like Traversable is a protocol, and since pathlib.Path implements the necessary methods, objects of type pathlib.Path should also be Traversable. And in fact:

    >>> from pathlib import Path
    >>> from importlib.resources.abc import Traversable
    >>> p = Path('.')
    >>> isinstance(p, Path)
    True
    >>> isinstance(p, Traversable)
    True
    

    So you should be able to write:

    def process_file(file_to_process: Traversable) -> None: ...
    

    I've checked, and mypy seems happy with the above annotation when calling process_file(Path('example.txt')).