Why do I get "'str' object has no attribute 'read'" when trying to use `json.load` on a string? [duplicate]
Asked Answered
S

10

227

In Python I'm getting an error:

Exception:  (<type 'exceptions.AttributeError'>,
AttributeError("'str' object has no attribute 'read'",), <traceback object at 0x1543ab8>)

Given python code:

def getEntries (self, sub):
    url = 'http://www.reddit.com/'
    if (sub != ''):
        url += 'r/' + sub
    
    request = urllib2.Request (url + 
        '.json', None, {'User-Agent' : 'Reddit desktop client by /user/RobinJ1995/'})
    response = urllib2.urlopen (request)
    jsonStr = response.read()
    
    return json.load(jsonStr)['data']['children']

What does this error mean and what did I do to cause it?

Schweiz answered 24/6, 2012 at 0:12 Comment(0)
B
282

The problem is that for json.load you should pass a file like object with a read function defined. So either you use json.load(response) or json.loads(response.read()).

Baranowski answered 24/6, 2012 at 0:33 Comment(8)
I don't understand this...how does doing read() solve the problem? The response still doesn't have a read function. Are we supposed to put the string in some object with a read function?Gobbler
@yourfriendzak read closely, it is two different functions with very similar names. json.load() takes a file like object with a read() method, json.loads() takes a string. It's easy to miss the "s" at the end and think they are the same method.Cismontane
Thanks to Joshmaker's comment, json.loads() can parse string for JSON data!Mucronate
@yourfriendzak This answer would point you that with open you can achieve that.Photocomposition
Thanks Joshmaker. Your andwe is useful to me. load, loads ....How un-intuitive names given by originators of library. Really illogicalSoho
@MANISHZOPE the s stands for "string". I agree that the standard library has some serious issues overall with how things are named, and this is a good example of how it gets messed up.Towandatoward
@kosii I request you to what @Cismontane said in your answer. It would be more helpful to users who just tent to overlook that tiny sLongways
I hope the person who thought json.loads was more self-explanatory than json.load_string has been fired right after the release.Delusive
R
65

Ok, this is an old thread but. I had a same issue, my problem was I used json.load instead of json.loads

This way, json has no problem with loading any kind of dictionary.

Official documentation

json.load - Deserialize fp (a .read()-supporting text file or binary file containing a JSON document) to a Python object using this conversion table.

json.loads - Deserialize s (a str, bytes or bytearray instance containing a JSON document) to a Python object using this conversion table.

Recess answered 20/12, 2019 at 9:28 Comment(0)
D
41

You need to open the file first. This doesn't work:

json_file = json.load('test.json')

But this works:

f = open('test.json')
json_file = json.load(f)
Dace answered 2/3, 2020 at 16:31 Comment(2)
I found the error in the question when trying to open a file instead of a request response in the question. Clearly, at the backend, json is treating both similarly, and so this answer helped me. Clearly worth an upvote.Perfuse
This answer is so straightforward. Thank you!Battista
D
19

If you get a python error like this:

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

You probably poisoned your object accidentally by overwriting your object with a string.

How to reproduce this error in python with a few lines of code:

#!/usr/bin/env python
import json
def foobar(json):
    msg = json.loads(json)

foobar('{"batman": "yes"}')

Run it, which prints:

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

But change the name of the variablename, and it works fine:

#!/usr/bin/env python
import json
def foobar(jsonstring):
    msg = json.loads(jsonstring)

foobar('{"batman": "yes"}')

This error is caused when you tried to run a method within a string. String has a few methods, but not the one you are invoking. So stop trying to invoke a method which String does not define and start looking for where you poisoned your object.

Dextroglucose answered 29/10, 2014 at 19:51 Comment(1)
"loads" worked for me. Thank you for your solutionKaciekacy
T
18
AttributeError("'str' object has no attribute 'read'",)

This means exactly what it says: something tried to find a .read attribute on the object that you gave it, and you gave it an object of type str (i.e., you gave it a string).

The error occurred here:

json.load(jsonStr)['data']['children']

Well, you aren't looking for read anywhere, so it must happen in the json.load function that you called (as indicated by the full traceback). That is because json.load is trying to .read the thing that you gave it, but you gave it jsonStr, which currently names a string (which you created by calling .read on the response).

Solution: don't call .read yourself; the function will do this, and is expecting you to give it the response directly so that it can do so.

You could also have figured this out by reading the built-in Python documentation for the function (try help(json.load), or for the entire module (try help(json)), or by checking the documentation for those functions on http://docs.python.org .

Towandatoward answered 24/6, 2012 at 2:19 Comment(0)
A
6

Instead of json.load() use json.loads() and it would work: ex:

import json
from json import dumps

strinjJson = '{"event_type": "affected_element_added"}'
data = json.loads(strinjJson)
print(data)
Andreasandree answered 30/7, 2021 at 23:12 Comment(0)
U
1

Open the file as a text file first

json_data = open("data.json", "r")

Now load it to dict

dict_data = json.load(json_data)
Uboat answered 8/12, 2022 at 9:27 Comment(0)
S
0

So, don't use json.load(data.read()) use json.loads(data.read()):

def findMailOfDev(fileName):
    file=open(fileName,'r')
    data=file.read();
    data=json.loads(data)
    return data['mail']
Standford answered 5/6, 2022 at 5:13 Comment(0)
T
0

use json.loads() function , put the s after that ... just a mistake btw i just realized after i searched error

def getEntries (self, sub):
url = 'http://www.reddit.com/'
if (sub != ''):
    url += 'r/' + sub

request = urllib2.Request (url + 
    '.json', None, {'User-Agent' : 'Reddit desktop client by /user/RobinJ1995/'})
response = urllib2.urlopen (request)
jsonStr = response.read()

return json.loads(jsonStr)['data']['children']

try this

Turgeon answered 17/8, 2022 at 15:19 Comment(0)
P
0

If you need to convert string to json. Then use loads() method instead of load(). load() function uses to load data from a file so used loads() to convert string to json object.

j_obj = json.loads('["label" : "data"]')
Pogrom answered 12/1, 2023 at 22:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.