AttributeError: 'str' object has no attribute 'read' (tested fix)
AttributeError: 'str' object has no attribute 'read' almost always means you passed a filename (or JSON text) to a function that wants an open file, most often json.load(). We tested the common mix-ups in Python 3.13, including one that gives no error at all.
1. Passing a filename where a file object is expected
Functions like json.load() call .read() on what you give them. A path is a str, and str has no .read(). We tried the common mix-ups:
import csv, json, os, tempfile
path = os.path.join(tempfile.mkdtemp(), "data.json")
open(path, "w").write('{"a": 1}')
def show(label, fn):
try:
print(f"{label:34} OK: {fn()!r}")
except Exception as e:
print(f"{label:34} {type(e).__name__}: {e}")
show("json.load(path)", lambda: json.load(path))
show("json.load(open(path))", lambda: json.load(open(path)))
show("json.loads(text)", lambda: json.loads('{"a": 1}'))
show("json.loads(open(path))", lambda: json.loads(open(path)))
show("csv.reader(path)", lambda: list(csv.reader(path))[:3])
Output:
json.load(path) AttributeError: 'str' object has no attribute 'read'
json.load(open(path)) OK: {'a': 1}
json.loads(text) OK: {'a': 1}
json.loads(open(path)) TypeError: the JSON object must be str, bytes or bytearray, not TextIOWrapper
csv.reader(path) OK: [['/'], ['t'], ['m']]
The rule: json.load takes an open file, while json.loads (the "s" is for string) takes the text. Mixing them up gives 'str' object has no attribute 'read' in one direction and the JSON object must be str, bytes or bytearray, not TextIOWrapper in the other. The correct form for a file is:
with open(path, encoding="utf-8") as f:
data = json.load(f)
The last line of the output is the dangerous one: csv.reader(path) raises nothing. It treats the string as an iterable of lines, so every character of the path becomes its own row (['/'], ['t'], ['m']). If your CSV rows are single characters of a file path, you passed the path instead of open(path, newline=""). Other APIs that take a file object fail differently: pickle.load(path) raises TypeError: file must have 'read' and 'readline' attributes. For other JSON errors see our JSON error handling guide.
Frequently asked questions
How do I fix 'str' object has no attribute 'read' with json.load?
Open the file first: with open(path) as f: data = json.load(f). If you already have the JSON text in a string, use json.loads(text).
What is the difference between json.load and json.loads?
json.load reads from an open file object; json.loads parses a str/bytes. Passing the wrong type raises AttributeError or TypeError.
Why does csv.reader give one character per row?
You passed the path string instead of an open file. csv.reader iterates the string character by character without raising an error.
Written with AI assistance. Measured on 2026-10-22 on Debian with Python 3.13.5: json.load and json.loads given a path, an open file and text, and csv.reader given a path. Every block was run verbatim and its output pasted unedited. PlainHeaders is our extension; Python is free.