Подтвердить что ты не робот

Python 2 и Python 3 - форматы urllib

Мне очень надоело пытаться выяснить, почему этот код работает в Python 2, а не в Python 3. Я просто пытаюсь захватить страницу json, а затем проанализировать ее. Здесь код в Python 2:

import urllib, json
response = urllib.urlopen("http://reddit.com/.json")
content = response.read()
data = json.loads(content)

Я думал, что эквивалентный код в Python 3 будет следующим:

import urllib.request, json
response = urllib.request.urlopen("http://reddit.com/.json")
content = response.read()
data = json.loads(content)

Но он взрывается мне в лицо, потому что данные, возвращаемые read(), являются типами "байтов". Тем не менее, я не могу для жизни меня заставить его преобразовать в то, что json сможет анализировать. Я знаю из заголовков, что reddit пытается отправить utf-8 мне, но я не могу заставить байты декодироваться в utf-8:

import urllib.request, json
response = urllib.request.urlopen("http://reddit.com/.json")
content = response.read()
data = json.loads(content.decode("utf8"))

Что я делаю неправильно?

Изменить: проблема в том, что я не могу получить данные в полезное состояние; хотя json загружает данные, часть которых не отображается, и я хочу иметь возможность печатать данные на экране.

Второе редактирование: похоже, проблема связана скорее с печатью, чем с парсингами. Ответ Alex предоставляет способ для script работать в Python 3, установив IO в utf8. Но остается вопрос: почему код работает в Python 2, но не Python 3?

4b9b3361

Ответ 1

Вы, вероятно, из-за неправильных операций вырезания и вставки, потому что они явно неправильны в обеих версиях (f.read() не работает, потому что нет f barename определено).

В Py3, ur = response.decode('utf8') работает отлично для меня, как и следующее json.loads(ur). Возможно, неправильные копии и пасты повлияли на ваши попытки преобразования 2-в-3.

Ответ 2

Зависит от вашей версии python, вы должны выбрать правильную библиотеку.

для python 3.5

import urllib.request
data = urllib.request.urlopen(url).read().decode('utf8')

для python 2.7

import urllib
url = serviceurl + urllib.urlencode({'sensor':'false', 'address': address})   
uh = urllib.urlopen(url)

Ответ 3

См. который отвечает в другом вопросе, связанном с Юникодом.

Теперь: тип Python 3 str (который был Python 2 unicode) - идеализированный объект, в том смысле, что он имеет дело с "символами", а не "байтами". Эти символы, чтобы использоваться для/из данных диска/сети, должны быть закодированы в/декодированы - из байтов с помощью "таблицы преобразования", кодировки a.k.a кодировки a.k.a. Из-за разнообразия операционной системы Python исторически избегало догадываться, что такое кодировка; это менялось с годами, но все же принцип "перед лицом двусмысленности, отказаться от соблазна угадать". применяется.

К счастью, веб-сервер упрощает вашу работу. Ваш response выше должен предоставить вам всю дополнительную информацию:

>>> response.headers['content-type']
'application/json; charset=UTF-8'

Итак, каждый раз, когда вы отправляете запрос на веб-сервер, проверяйте заголовок Content-Type для значения кодировки и декодируйте данные запроса в Unicode (Python 3: bytes.decode(charset)str), используя эту кодировку.