AttributeError (“o objeto 'str' não tem atributo 'read'”)

134

No Python, estou recebendo um erro:

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

Dado código 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']

O que esse erro significa e o que eu fiz para causá-lo?

RobinJ
fonte
187
Eu gosto do jsonofabitchnome da variável
Mon Calamari
6
Haha! O que é esse "jsonofabitch"? : D
Bahadir Tasdemir
13
Parece que os moderadores de Stackoverflow tem um senso de humor, para uma mudança ...
Pepito Fernandez
6
2019 e isso ainda é engraçado: P
Rishav
1
Na verdade, fez o meu dia, obrigado do futuro :)
Pesche Helfer

Respostas:

187

O problema é que, para json.loadvocê, deve passar um arquivo como objeto com uma readfunção definida. Então você usa json.load(response)ou json.loads(response.read()).

Kosii
fonte
3
Eu não entendo isso ... como o read () resolve o problema? A resposta ainda não tem uma função de leitura. Devemos colocar a string em algum objeto com uma função de leitura?
Zakdances 11/08
85
@yourfriendzak leia atentamente, são duas funções diferentes com nomes muito semelhantes. json.load()pega um arquivo como objeto com um read()método, json.loads()pega uma string. É fácil perder os "s" no final e pensar que eles são o mesmo método.
Joshmaker
4
Graças ao comentário de Joshmaker, json.loads () pode analisar a cadeia de caracteres para dados JSON!
Yu Shen
2
@yourfriendzak Esta resposta indica que openvocê pode conseguir isso.
chaim
1
@MANISHZOPE ssignifica "string". Concordo que a biblioteca padrão tem alguns problemas sérios no geral com a maneira como as coisas são nomeadas, e este é um bom exemplo de como é confuso.
Karl Knechtel
13
AttributeError("'str' object has no attribute 'read'",)

Isso significa exatamente o que diz: algo tentou encontrar um .readatributo no objeto que você deu e um objeto do tipo str(ou seja, você deu uma string).

O erro ocorreu aqui:

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

Bem, você não está procurando readnenhum lugar, portanto, isso deve acontecer na json.loadfunção que você chamou (como indicado pelo rastreamento completo). Isso é porque json.loadestá tentando .reada coisa que você deu, mas você deu jsonofabitch, que atualmente nomeia uma string (que você criou chamando .readno response).

Solução: não chame .reada si mesmo; a função fará isso e espera que você dê o responsediretamente para que ele possa fazê-lo.

Você também pode ter descoberto isso lendo a documentação interna do Python para a função (try help(json.load)ou para todo o módulo (try help(json))) ou verificando a documentação dessas funções em http://docs.python.org .

Karl Knechtel
fonte
Foi assim que o OP chamou. Estou sempre em dúvida sobre mudar ou preservar esses nomes de identificador ao ajudar outras pessoas. : /
Karl Knechtel
Oh, você está certo, eu desnatado isso ... Eu não estava reclamando, embora :)
Andrea Ligios
12

Se você receber um erro python como este:

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

Você provavelmente envenenou seu objeto acidentalmente substituindo-o por uma string.

Como reproduzir esse erro em python com algumas linhas de código:

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

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

Execute-o, que imprime:

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

Mas mude o nome do nome da variável e ele funciona bem:

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

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

Este erro é causado quando você tenta executar um método dentro de uma string. String possui alguns métodos, mas não o que você está chamando. Portanto, pare de tentar invocar um método que String não define e comece a procurar onde você envenenou seu objeto.

Eric Leschinski
fonte
7

Ok, este é um tópico antigo, mas. Eu tive um mesmo problema, meu problema foi usar em json.loadvez dejson.loads

Dessa forma, o json não tem nenhum problema em carregar qualquer tipo de dicionário.

Documentação oficial

json.load - Desserializa o fp (a .read () - suportando arquivo de texto ou arquivo binário que contém um documento JSON) para um objeto Python usando esta tabela de conversão.

json.loads - desserializa s (uma instância de str, bytes ou bytearray que contém um documento JSON) para um objeto Python usando esta tabela de conversão.

JohnyMSF
fonte
5

Você precisa abrir o arquivo primeiro. Isso não funciona:

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

Mas isso funciona:

f = open('test.json')
json_file = json.load(f)
Richard Liang
fonte
2
Encontrei o erro na pergunta ao tentar abrir um arquivo em vez de uma resposta de solicitação na pergunta. Claramente, no back-end, o json está tratando os dois da mesma forma e, portanto, essa resposta me ajudou. Claramente vale a pena votar.
Nitin Khanna