AttributeError («l'objet 'str' n'a pas d'attribut 'read'»)

134

En Python, j'obtiens une erreur:

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

Compte tenu du code python:

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)
    jsonofabitch = response.read ()

    return json.load (jsonofabitch)['data']['children']

Que signifie cette erreur et qu'ai-je fait pour la provoquer?

RobinJ
la source
188
J'aime le jsonofabitchnom de variable.
Mon Calamari
6
Haha! C'est quoi ce "jsonofabitch"? : D
Bahadir Tasdemir
13
On dirait que les modérateurs de Stackoverflow ont le sens de l'humour, pour un changement ...
Pepito Fernandez
6
2019 et c'est toujours drôle: P
Rishav
1
En effet, fait ma journée, merci du futur :)
Pesche Helfer

Réponses:

187

Le problème est que pour json.loadvous devez passer un fichier comme un objet avec une readfonction définie. Donc, soit vous utilisez json.load(response)ou json.loads(response.read()).

kosii
la source
3
Je ne comprends pas ça ... comment faire read () résout-il le problème? La réponse n'a toujours pas de fonction de lecture. Sommes-nous censés mettre la chaîne dans un objet avec une fonction de lecture?
zakdances
85
@yourfriendzak a lu attentivement, ce sont deux fonctions différentes avec des noms très similaires. json.load()prend un fichier comme un objet avec une read()méthode, json.loads()prend une chaîne. Il est facile de rater le «s» à la fin et de penser qu'il s'agit de la même méthode.
Joshmaker
4
Grâce au commentaire de Joshmaker, json.loads () peut analyser la chaîne pour les données JSON!
Yu Shen
2
@yourfriendzak Cette réponse vous indiquerait qu'avec openvous pouvez y parvenir.
chaim
1
@MANISHZOPE ssignifie "chaîne". Je conviens que la bibliothèque standard a globalement de sérieux problèmes avec la façon dont les choses sont nommées, et c'est un bon exemple de la façon dont elle est gâchée.
Karl Knechtel le
13
AttributeError("'str' object has no attribute 'read'",)

Cela signifie exactement ce qu'il dit: quelque chose a essayé de trouver un .readattribut sur l'objet que vous lui avez donné, et vous lui avez donné un objet de type str(c'est-à-dire que vous lui avez donné une chaîne).

L'erreur s'est produite ici:

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

Eh bien, vous ne cherchez readnulle part, donc cela doit se produire dans la json.loadfonction que vous avez appelée (comme indiqué par le traçage complet). C'est parce que vous json.loadessayez de .readla chose que vous lui avez donnée, mais vous l'avez donnée jsonofabitch, qui nomme actuellement une chaîne (que vous avez créée en appelant .readle response).

Solution: ne vous appelez .readpas; la fonction fera cela, et attend de vous que vous lui donniez responsedirectement pour qu'elle puisse le faire.

Vous pourriez également avoir compris cela en lisant la documentation Python intégrée pour la fonction (essayez help(json.load), ou pour le module entier (essayez help(json)), ou en consultant la documentation de ces fonctions sur http://docs.python.org .

Karl Knechtel
la source
C'est comme ça qu'OP l'a appelé. Je ne sais toujours pas si je dois changer ou conserver ces noms d'identifiants lorsque j'aide les autres. : /
Karl Knechtel
Oh, tu as raison, je l'ai écumé ... Je ne me plaignais pas, cependant :)
Andrea Ligios
12

Si vous obtenez une erreur python comme celle-ci:

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

Vous avez probablement empoisonné votre objet accidentellement en écrasant votre objet avec une chaîne.

Comment reproduire cette erreur en python avec quelques lignes de code:

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

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

Exécutez-le, qui imprime:

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

Mais changez le nom du nom de la variable, et cela fonctionne bien:

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

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

Cette erreur se produit lorsque vous essayez d'exécuter une méthode dans une chaîne. String a quelques méthodes, mais pas celle que vous appelez. Alors arrêtez d'essayer d'appeler une méthode que String ne définit pas et commencez à chercher où vous avez empoisonné votre objet.

Eric Leschinski
la source
7

Ok, c'est un vieux fil mais. J'ai eu le même problème, mon problème était que j'avais utilisé json.loadau lieu dejson.loads

De cette façon, json n'a aucun problème avec le chargement de tout type de dictionnaire.

Documentation officielle

json.load - Désérialise fp (un .read () - fichier texte de prise en charge ou fichier binaire contenant un document JSON) en un objet Python à l'aide de cette table de conversion.

json.loads - Désérialise s (une instance de chaîne, d'octets ou de bytearray contenant un document JSON) en un objet Python à l'aide de cette table de conversion.

JohnyMSF
la source
5

Vous devez d'abord ouvrir le fichier. Cela ne fonctionne pas:

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

Mais cela fonctionne:

f = open('test.json')
json_file = json.load(f)
Richard Liang
la source
2
J'ai trouvé l'erreur dans la question en essayant d'ouvrir un fichier au lieu d'une réponse de demande dans la question. De toute évidence, en backend, json traite les deux de la même manière, et cette réponse m'a donc aidé. Vaut clairement un vote positif.
Nitin Khanna le