This error typically occurs when you try to read the string pointing to the path of a file instead of a file object. To solve this error, you should use the appropriate method for reading the path of a file or reading a file object.

Generally, when reading in an object using a function, check to see what data type the function expects in its documentation.

This tutorial will go through the error in detail and solve it with code examples.


AttributeError: ‘str’ object has no attribute ‘read’

AttributeError occurs in a Python program when we try to access an attribute (method or property) that does not exist for a particular object. The part “‘str’ object has no attribute ‘read’” tells us that the string object does not have the attribute read(). The read() method belongs to the File data type and returns the specified number of bytes from the file. The syntax of the read method is as follows:

file.read()

Parameters:

  • size: Optional. The number of bytes to return. The default is -1, which means the whole file.

Let’s look at an example of using the read() method to read a file. The text file is ‘test.txt’ and has the following contents:

test

The code is as follows:

f = open('test.txt', 'r')
print(type(f))
print(f.read())

The open() function opens a file and returns it as a file object. The parameter ‘r’ sets the function to read. We also print the type of f object to verify it is a file object. Let’s run the code to see the result:

<class '_io.TextIOWrapper'>
test

TextIOWrapper object is a text stream that allows us to access the file’s contents as a list of strings.

Let’s see what happens when we try to call read() on a string representing the filename:

f = 'test.txt'
print(type(f))
print(f.read())
<class 'str'>
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-7-d6f605ca887b> in <module>
      1 f = 'test.txt'
      2 print(type(f))
----> 3 print(f.read())

AttributeError: 'str' object has no attribute 'read'

We raise the AttributeError because the read() method is only suitable for File objects. We cannot read a file by calling read() on the filename string.

Example: Using json.load()

The error commonly occurs when using the json library to read a JSON string instead of a JSON file object. There are two different methods in the json library:

  • json.load(): Deserializes a text or binary file containing a JSON document to a Python object
  • json.loads(): Deserializes a str, bytes, or bytearray instance containing a JSON document to a Python object

If you have a JSON string, you must use json.loads() if you use json.load() instead, you will raise the AttributeError.

Let’s look at an example where we want to make an HTTP POST request to httpbin. We will read a string into the program using open() and create a JSON payload to post to the specified URL.

The text file star_wars.txt contains the following dictionary:

{"id": 1, "name": "Anakin", "passion": "podracing"}

The code to load and POST the payload is as follows:

import requests
import json
 
url = "https://httpbin.org/post"
 
headers = {
           'Content-Type': 'application/json',
           'Accept': 'application/json'
}
 
infile = open('star_wars.txt', 'r')

string = infile.readline()

payload = json.load(string)

response = requests.post(url, json=payload, params=params, headers=headers)

print("Status code: ", response.status_code)

print("Response as JSON: ", response.json())
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-1-fae504fd2214> in <module>
     10 string = infile.readline()
     11 
---> 12 payload = json.load(string)
     13 
     14 x = request.post(url, json=payload, params=params, headers=headers)

~/opt/anaconda3/lib/python3.8/json/__init__.py in load(fp, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
    291     kwarg; otherwise ``JSONDecoder`` is used.
    292     """
--> 293     return loads(fp.read(),
    294         cls=cls, object_hook=object_hook,
    295         parse_float=parse_float, parse_int=parse_int,

AttributeError: 'str' object has no attribute 'read'

The error occurs because the json.load() method expects a File object as a parameter but instead receives a string.

Solution

We need to use json.loads() to solve this error. Let’s look at the revised code:

import requests
import json
 
url = "https://httpbin.org/post"
 
headers = {
           'Content-Type': 'application/json',
           'Accept': 'application/json'
}
 
infile = open('star_wars.txt', 'r')

string = infile.readline()

payload = json.loads(string)

response = requests.post(url, json=payload, params=params, headers=headers)

print("Status code: ", response.status_code)
print("Response as JSON: ", response.json())

Let’s run the code to get the result:

Status code:  200
Response as JSON:  {'args': {'priority': 'normal'}, 'data': '{"id": 1, "name": "Anakin", "passion": "podracing"}', 'files': {}, 'form': {}, 'headers': {'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate, br', 'Content-Length': '51', 'Content-Type': 'application/json', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.27.1', 'X-Amzn-Trace-Id': 'Root=1-622bd6f5-3122393306eab3cd6df2c488'}, 'json': {'id': 1, 'name': 'Anakin', 'passion': 'podracing'}, 'origin': '90.206.95.191', 'url': 'https://httpbin.org/post?priority=normal'}

The status code 200 tells us we successfully made the HTTP request and retrieved the response.

Summary

Congratulations on reading to the end of this tutorial! The AttributeError: ‘str’ object has no attribute ‘read’ occurs when you call the read() method on a string object. You may encounter this when using the json library as there are two distinct methods load() for File objects and loads() string and byte objects. Ensure that you use the json.loads() method when you want to access the contents JSON string.

For further reading on AttributeErrors, go to the articles:

To learn more about Python for data science and machine learning, go to the online courses page on Python for the most comprehensive courses available.

Have fun and happy researching!