ReaL_HarDCorE
@ReaL_HarDCorE

Как установить правильную кодировку для ответа с сервера в Python 3?

Здравствуйте. Пишу софтину на Python 3. Нужно сделать запрос к серверу, чтобы тот вернул обычный JSON. Работаю с кодировкой UTF-8. Эта кодировка указана везде: в конфиге сервера, в заголовке PHP-скрипта, в Python-скрипте (# -*- coding: utf-8 -*-), сами файлы скриптов тоже в UTF-8. Но при попытке раскодировать пришедший ответ из UTF-8, появляется ошибка:

[Decode error - output not utf-8]

А если раскодировать ответ кодировкой cp1251, то всё прекрасно работает. Мне интересно, откуда взялась эта кодировка?

Код на питоне:
from urllib.request import Request, urlopen
from urllib.parse import urlencode
import json

req = Request("http://devcave.ru/json.php")
response = urlopen(req)
data = response.read().decode('cp1251') # .decode('utf-8') вызывает ошибку, описанную выше 
data = json.loads(data)

print(response.headers.get_content_charset())
print(data)

Вывод кода на питоне:

utf-8
{'key': 'русский язык'}

PHP-код на сервере:
header('Content-Type: application/json;charset=utf-8');
echo json_encode(array('key' => 'русский язык'), JSON_UNESCAPED_UNICODE);


Решено:
На самом деле при декодировании строки вместо cp1251 можно и нужно было использовать utf-8 - при этом всё проходит без ошибок, что означат, что все кодировки везде настроены правильно.
Проблема была в функции print, которая отказывалась выводить раскодированную строку и становилась инициатором ошибки.
Последствия перехода с Python 2 на 3.
Спасибо всем, кто пытался помочь)
  • Вопрос задан
  • 3794 просмотра
Решения вопроса 1
adugin
@adugin Куратор тега Python
В Python 2.7 работает и так, и так :)
>>> data = urlopen('http://devcave.ru/json.php').read()
>>> data.decode('utf-8')
u'{"key":"\\u0440\\u0443\\u0441\\u0441\\u043a\\u0438\\u0439 \\u044f\\u0437\\u044b\\u043a"}'
>>> data.decode('cp1251')
u'{"key":"\\u0440\\u0443\\u0441\\u0441\\u043a\\u0438\\u0439 \\u044f\\u0437\\u044b\\u043a"}'
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
qmax
@qmax
программер
Кодировку ответа с сервера нужно устанавливать на сервере.
Ответ написан
Комментировать
yokotoka
@yokotoka
Python guru
Походу сервер криво настроен. Apache? Нужно чтобы он не пытался в эту нелепую cp1251 перекодировать всё. Ну либо править на стороне скрипта - делать .decode('cp1251') для данных, которые вы от сервера получаете, если сервер не ваш, как вы уже и делаете. Это переведёт строку в unicode, с которой можно нормально дальше работать.

Короче, сервер врёт, что отдаёт utf-8. По факту он отдаёт вам cp1251. И Python вам об этом сообщил.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы