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

Ошибка 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, он отлично работает.

4b9b3361

Ответ 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.