Python 2 против Python 3 - форматы urllib - PullRequest
21 голосов
/ 28 июня 2010

Мне очень надоело пытаться понять, почему этот код работает в 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 загружает данные, часть их не отображается, и я хочу иметь возможность выводить данные на экран.

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

Ответы [ 3 ]

15 голосов
/ 28 июня 2010

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

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

7 голосов
/ 27 октября 2015

В зависимости от вашей версии Python вы должны выбрать правильную библиотеку.

для питона 3,5

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

для питона 2.7

import urllib
url = serviceurl + urllib.urlencode({'sensor':'false', 'address': address})   
uh = urllib.urlopen(url)
0 голосов
/ 17 октября 2011

Пожалуйста, смотрите , что ответьте на другой вопрос, связанный с Unicode.

Теперь: тип 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), используя этот набор символов. .

...