Com o Python 3, estou solicitando um documento json a partir de uma URL.
response = urllib.request.urlopen(request)
O response
objeto é um objeto parecido com um arquivo com read
e readline
métodos. Normalmente, um objeto JSON pode ser criado com um arquivo aberto no modo de texto.
obj = json.load(fp)
O que eu gostaria de fazer é:
obj = json.load(response)
No entanto, isso não funciona, pois o urlopen retorna um objeto de arquivo no modo binário.
Uma solução alternativa é, obviamente:
str_response = response.read().decode('utf-8')
obj = json.loads(str_response)
mas isso parece ruim ...
Existe uma maneira melhor de transformar um objeto de arquivo de bytes em um objeto de arquivo de string? Ou estou faltando algum parâmetro para uma codificação urlopen
ou json.load
para ela?
Respostas:
HTTP envia bytes. Se o recurso em questão for texto, a codificação de caracteres é normalmente especificada, pelo cabeçalho HTTP do tipo de conteúdo ou por outro mecanismo (um RFC, HTML
meta http-equiv
, ...).urllib
devemos saber como codificar os bytes para uma string, mas é muito ingênuo - é uma biblioteca terrivelmente fraca e não-Pythonic.Dive Into Python 3 fornece uma visão geral sobre a situação.
Sua "solução alternativa" está correta - embora pareça errado, é a maneira correta de fazê-lo.
fonte
urlopen
deve ser capaz de decodificar os bytes em si, pois conhece a codificação. De qualquer forma, publiquei a solução da biblioteca padrão do Python como resposta - você pode fazer decodificação de fluxo de bytes usando ocodecs
módulo.Maravilhosa biblioteca padrão do Python para o resgate…
Funciona com py2 e py3.
Documentos: Python 2 , Python3
fonte
python 3.4.3
não sei por que? O erro foiTypeError: the JSON object must be str, not 'StreamReader'
json.loads()
vez dejson.load()
?response.headers.get_content_charset()
. RetornaNone
se não houver codificação e não existir no python2.Cheguei à opinião de que a pergunta é a melhor resposta :)
fonte
Para qualquer outra pessoa que tente resolver isso usando a
requests
biblioteca:fonte
requests
: você pode simplesmente fazer issor.json()
json.loads
. Tudo o que você precisa fazer ér.json()
e já tem seu objeto JSON carregado em um dict.*** UnicodeEncodeError: 'ascii' codec can't encode characters in position 264-265: ordinal not in range(128)
Este funciona para mim, usei a biblioteca 'request' com o
json()
check-out do documento em pedidos para humanosfonte
Eu tive problemas semelhantes usando o Python 3.4.3 e 3.5.2 e o Django 1.11.3. No entanto, quando atualizei para o Python 3.6.1, os problemas desapareceram.
Você pode ler mais sobre isso aqui: https://docs.python.org/3/whatsnew/3.6.html#json
Se você não está vinculado a uma versão específica do Python, considere atualizar para a 3.6 ou posterior.
fonte
Se você estiver enfrentando esse problema ao usar a microframework do balão, poderá fazer o seguinte:
data = json.loads(response.get_data(as_text=True))
Na documentação : "Se as_text estiver definido como True, o valor retornado será uma string unicode decodificada"
fonte
Sua solução alternativa realmente me salvou. Eu estava tendo muitos problemas ao processar a solicitação usando a estrutura Falcon. Isso funcionou para mim. req sendo o formulário de requisição curl pr httpie
fonte
Isso transmitirá os dados de bytes para o json.
io.TextIOWrapper é preferível ao leitor de módulo do codec. https://www.python.org/dev/peps/pep-0400/
fonte
json.loads(bytes_obj.decode())
.Acabei de encontrar este método simples para criar conteúdo HttpResponse como um json
Espero que ajude você
fonte
No Python 3.6, você pode usar
json.loads()
para desserializar umbytes
objeto diretamente (a codificação deve ser UTF-8, UTF-16 ou UTF-32). Portanto, usando apenas módulos da biblioteca padrão, você pode:fonte
Eu usei abaixo programa para usar de
json.loads()
fonte