AttributeError (“el objeto 'str' no tiene atributo 'read'”)

134

En Python obtengo un error:

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

Código de Python dado:

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']

¿Qué significa este error y qué hice para causarlo?

RobinJ
fuente
187
Me gusta el jsonofabitchnombre de la variable.
Mon Calamari
66
¡Jaja! ¿Qué es ese "jsonofabitch"? : D
Bahadir Tasdemir
13
Parece que los moderadores de Stackoverflow tienen sentido del humor, para variar ...
Pepito Fernández el
66
2019 y esto sigue siendo divertido: P
Rishav
1
De hecho, me alegraron el día, gracias desde el futuro :)
Pesche Helfer

Respuestas:

187

El problema es que json.loaddebe pasar un archivo como objeto con una readfunción definida. Entonces, o usas json.load(response)o json.loads(response.read()).

kosii
fuente
3
No entiendo esto ... ¿cómo hacer read () resuelve el problema? La respuesta aún no tiene una función de lectura. ¿Se supone que debemos poner la cadena en algún objeto con una función de lectura?
zakdances
85
@yourfriendzak leyó atentamente, son dos funciones diferentes con nombres muy similares. json.load()toma un archivo como objeto con un read()método, json.loads()toma una cadena. Es fácil pasar por alto la "s" al final y pensar que son el mismo método.
Joshmaker
44
Gracias al comentario de Joshmaker, json.loads () puede analizar cadenas para datos JSON.
Yu Shen
2
@yourfriendzak Esta respuesta le indicaría que con openusted puede lograr eso.
chaim
1
@MANISHZOPE ssignifica "cadena". Estoy de acuerdo en que la biblioteca estándar tiene algunos problemas serios en general con la forma en que se nombran las cosas, y este es un buen ejemplo de cómo se complica.
Karl Knechtel el
13
AttributeError("'str' object has no attribute 'read'",)

Esto significa exactamente lo que dice: algo intentó encontrar un .readatributo en el objeto que le dio, y le dio un objeto de tipo str(es decir, le dio una cadena).

El error ocurrió aquí:

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

Bueno, no está buscando readningún lugar, por lo que debe suceder en la json.loadfunción que llamó (como lo indica el rastreo completo). Eso es porque json.loadestá intentando .readlo que le diste, pero lo diste jsonofabitch, que actualmente nombra una cadena (que creaste llamando .readal response).

Solución: no te llames a .readti mismo; la función hará esto, y espera que le des el responsedirectamente para que pueda hacerlo.

También podría haber descubierto esto leyendo la documentación de Python incorporada para la función (try help(json.load), o para todo el módulo (try help(json)), o comprobando la documentación de esas funciones en http://docs.python.org .

Karl Knechtel
fuente
Así lo llamó OP. Siempre estoy en la cerca sobre si cambiar o preservar dichos nombres de identificación cuando ayudo a otros. : /
Karl Knechtel
Oh, tienes razón, lo he leído ... Aunque no me estaba quejando :)
Andrea Ligios
12

Si obtiene un error de Python como este:

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

Probablemente envenenó su objeto accidentalmente sobrescribiendo su objeto con una cadena.

Cómo reproducir este error en Python con algunas líneas de código:

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

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

Ejecútelo, que imprime:

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

Pero cambie el nombre del variablename y funciona bien:

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

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

Este error se produce cuando intentaste ejecutar un método dentro de una cadena. La cadena tiene algunos métodos, pero no el que estás invocando. Así que deja de intentar invocar un método que String no define y comienza a buscar dónde envenenaste tu objeto.

Eric Leschinski
fuente
7

Ok, este es un hilo viejo pero. Tuve el mismo problema, mi problema fue que usé en json.loadlugar dejson.loads

De esta manera, json no tiene problemas para cargar ningún tipo de diccionario.

Documentación oficial

json.load - Deserialize fp (un .read () - archivo de texto de soporte o archivo binario que contiene un documento JSON) a un objeto Python usando esta tabla de conversión.

json.loads: deserializa s (una instancia de str, bytes o bytearray que contiene un documento JSON) a un objeto Python usando esta tabla de conversión.

JohnyMSF
fuente
5

Primero debes abrir el archivo. Esto no funciona:

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

Pero esto funciona:

f = open('test.json')
json_file = json.load(f)
Richard Liang
fuente
2
Encontré el error en la pregunta al intentar abrir un archivo en lugar de una respuesta de solicitud en la pregunta. Claramente, en el backend, json está tratando a ambos de manera similar, por lo que esta respuesta me ayudó. Claramente vale la pena un voto a favor.
Nitin Khanna