Python3错误:initial_value必须是字符串或None,使用StringIO

84
在将代码从python2迁移到python3时,当从URL中读取内容时,出现以下错误:
TypeError:initial_value必须是str或NoneType,而不是bytes类型。
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,它可以正常工作。


请提供完整的回溯信息,好吗? - Anand S Kumar
它只是给出这个错误并停止了。 类型错误:initial_value必须是Unicode或None,而不是str。 - AMisra
你能否包含变量 url 的值?当我使用 url = 'http://www.google.com' 时,代码对我来说可以正常运行。 - maxymoo
1
如果您因为pandas.read_csv()在ASCII输入上推断错误的编码而来到这里,请使用encoding='utf8''latin1'来强制它。 - smci
4个回答

148

29

看起来像是另一个 Python3 中的 bytes 和 str 的问题。你的响应是 bytes 类型(在 Python 3 中与 str 不同),你需要先将其转换为字符串,使用 response.read().decode('utf-8'),然后在其上使用 StringIO。或者你也可以像有人建议的那样使用 BytesIO,但如果你期望其为 str,最好的方式是先将其解码为一个 str


我认为这是处理只能从StringIO和BytesIO读取的模块(例如Bio.SeqIO)的最佳答案,如records = SeqIO.parse(StringIO(r.read().decode('utf-8')), "fasta") - Brian Wiley

3

考虑使用six.StringIO而不是io.StringIO。

最初的回答

0
而且如果你正在将代码从Python2迁移到Python3并且使用旧版本的Suds,请在Python3中使用"suds-py3"。

目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community
虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅链接的答案可能会失效。-【来自审查】 - rv.kvetch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接