Read a package text resource with files
Also published in our Blogger archive.
importlib.resources.files() returns a traversable view of resources associated with a package or module. This example builds a temporary package named fixture_resources with an empty __init__.py and one UTF-8 resource, message.txt. After importing the package from the temporary directory, files(fixture_resources).joinpath("message.txt") selects that resource. read_text(encoding="utf-8") produces the exact string "hello resource\n"; the assertion includes the newline, and repr() makes it visible in deterministic output.
The fixture is isolated: it uses TemporaryDirectory, then removes both its temporary sys.path entry and package cache entry in finally. No real user path is printed or required. Passing the imported package object is explicit, so the resource anchor is clear.
A traversable resource is not necessarily an ordinary filesystem Path. Packages and resources may be loaded from a zip file, so code that merely needs text should prefer read_text() over assuming a local file exists. The resources API follows the security model of built-in open(), so resource names from untrusted input need appropriate validation. files() was added in Python 3.9; Python 3.12 renamed its keyword parameter from package to anchor. See the Python importlib.resources documentation.
import importlib
import importlib.resources
import sys
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
root = Path(directory)
package = root / "fixture_resources"
package.mkdir()
(package / "__init__.py").write_text("", encoding="utf-8")
(package / "message.txt").write_text("hello resource\n", encoding="utf-8")
sys.path.insert(0, directory)
try:
fixture_resources = importlib.import_module("fixture_resources")
text = (
importlib.resources.files(fixture_resources)
.joinpath("message.txt")
.read_text(encoding="utf-8")
)
assert text == "hello resource\n"
print(f"text: {text!r}")
finally:
sys.path.remove(directory)
sys.modules.pop("fixture_resources", None)
text: 'hello resource\n'
AI-assistance disclosure: AI helped draft this explanation and example.