Ошибка Python3: initial_value должно быть str или None
При переносе кода с python2
на 3
я получаю эту ошибку при чтении из URL
TypeError: initial_value должен быть str или None, а не байтами.
import urllib
import json
import gzip
from urllib.parse import urlencode
from urllib.request import Request
service_url = 'https://babelfy.io/v1/disambiguate'
text = 'BabelNet is both a multilingual encyclopedic dictionary and a semantic network'
lang = 'EN'
Key = 'KEY'
params = {
'text' : text,
'key' : Key,
'lang' :'EN'
}
url = service_url + '?' + urllib.urlencode(params)
request = Request(url)
request.add_header('Accept-encoding', 'gzip')
response = urllib.request.urlopen(request)
if response.info().get('Content-Encoding') == 'gzip':
buf = StringIO(response.read())
f = gzip.GzipFile(fileobj=buf)
data = json.loads(f.read())
Исключение выбрано в этой строке
buf = StringIO(response.read())
Если я использую python2, он отлично работает.
Ответы
Ответ 1
response.read()
возвращает экземпляр bytes
, а StringIO
является потоком в памяти только для текста. Вместо этого используйте BytesIO
.
От Что нового в Python 3.0 - Text Vs. Данные вместо Unicode Vs. 8-битный
Модули StringIO
и cStringIO
исчезли. Вместо этого импортируйте модуль io
и используйте io.StringIO
или io.BytesIO
для текста и данных соответственно.
Ответ 2
Это выглядит как еще одна проблема python3 bytes
vs. str
. Ваш ответ имеет тип bytes
(который отличается от python 3 из str
). Вам нужно сначала ввести его в строку, используя response.read().decode('utf-8')
, а затем использовать StringIO
. Или вы можете использовать BytesIO
, как кто-то сказал, но если вы ожидаете, что это будет str
, предпочтительный способ - decode
вначале str
.
Ответ 3
Попробуйте использовать six.StringIO вместо io.StringIO.