AttributeError: PosixPath object has no attribute read in Python
Use path.read_text() or path.read_bytes() to read pathlib Path objects directly, or open the file with open(path).read().
Root Cause Analysis
This error occurs when Python tries to call .read() directly on a pathlib.Path instance (such as PosixPath on Linux/macOS or WindowsPath on Windows), confusing the path object representation with an open file handle.
1. Path Objects vs File Descriptor Streams
In Python, a Path object from the pathlib module represents a filesystem path location (a path name), not an opened file handle stream. Open file objects (returned by open()) provide the .read() method, whereas Path objects provide .read_text() and .read_bytes().
2. API Confusion Between Pathlib and IO Objects
Developers familiar with file-like objects (such as io.StringIO or files returned by open()) frequently write path.read() out of habit, expecting the path to automatically open and read its contents.
3. Passing Path Objects to Functions Expecting File Buffers
Passing a Path object into functions expecting a readable stream (e.g. json.load(path) instead of json.load(open(path)) or json.loads(path.read_text())) fails because the function attempts to invoke path.read() internally.
4. Polymorphic File Handling in Libraries
Third-party libraries that support both file paths and open file objects will inspect hasattr(obj, 'read') to determine whether to call open().
Reproduction Code (MCVE)
from pathlib import Path
path = Path('config.json')
# Bug: calling .read() directly on a Path object
data = path.read()
Solution 1: Use path.read_text() for Direct Pathlib File Reading
Use path.read_text(encoding='utf-8') to read the entire file contents as a string in a single line.
import tempfile
from pathlib import Path
with tempfile.NamedTemporaryFile('w', delete=False, encoding='utf-8') as f:
f.write('Database config: host=localhost, port=5432')
temp_file = Path(f.name)
# Correct: use read_text() on Path objects
content = temp_file.read_text(encoding='utf-8')
print(f'Read text successfully: {content}')
temp_file.unlink()
Solution 2: Use open() Context Manager with Path
Pass the Path object into the standard open() context manager to obtain an authentic file stream with .read().
import tempfile
from pathlib import Path
with tempfile.NamedTemporaryFile('w', delete=False, encoding='utf-8') as f:
f.write('Stream contents via context manager')
temp_file = Path(f.name)
# Open file handle using Path object
with open(temp_file, 'r', encoding='utf-8') as f:
data = f.read()
print(f'File handle read: {data}')
temp_file.unlink()
A common mistake is using path.read_text() without specifying encoding='utf-8'. On Windows, Python defaults to the system ANSI code page (e.g. cp1252), which will raise UnicodeDecodeError when reading UTF-8 characters. Always pass encoding='utf-8'. Another edge case is reading binary data (images, pickle files): use path.read_bytes() instead of read_text(). Contrast this error with AttributeError: '_io.TextIOWrapper' object has no attribute 'exists', which occurs when attempting pathlib operations on open file handles.