如何提升Python下载解析JSON的速度?及json.load报错排查
问题解答
一、初始代码速度慢的原因与优化方向
你的初始代码速度比Java慢10倍的核心原因,几乎可以肯定是没有启用HTTP压缩。很多Java HTTP客户端会自动添加Accept-encoding: gzip, deflate请求头,服务器会返回压缩后的内容,体积大幅减小,传输速度自然更快;但Python标准库的urlopen默认不会添加这个头,服务器返回的是未压缩的原始JSON,当JSON体积较大时,下载耗时会显著增加。
你后来添加Accept-encoding请求头的思路完全正确,这是提升速度的关键一步。
二、json.load(fp)报错的原因与解决办法
你遇到的TypeError: the JSON object must be str, not 'bytes',问题出在GzipFile的默认工作模式上:
GzipFile默认以二进制模式打开文件对象,它的read()方法返回的是bytes类型数据;json.load()虽然支持传入文件对象,但要求该对象返回的是字符串(str),而非字节流。
这里有两种简单的解决方案:
方案1:将GzipFile以文本模式打开
修改gzip.GzipFile的初始化参数,指定mode='rt'(文本读取模式)并设置编码(比如utf-8),这样fp返回的就是字符串,json.load()就能正常解析:
def read_json_data(url_str: str): req = Request(url_str, headers={'Accept-encoding': 'gzip'}) with urlopen(req) as resp: if resp.info().get('Content-Encoding') == 'gzip': with gzip.GzipFile(fileobj=resp, mode='rt', encoding='utf-8') as fp: data = json.load(fp) else: data = json.load(resp) return data
方案2:用json.loads()手动解码字节流
如果不想修改GzipFile的模式,也可以先读取字节流,解码成字符串后再用json.loads()解析:
def read_json_data(url_str: str): req = Request(url_str, headers={'Accept-encoding': 'gzip'}) with urlopen(req) as resp: if resp.info().get('Content-Encoding') == 'gzip': with gzip.GzipFile(fileobj=resp) as fp: data_bytes = fp.read() data = json.loads(data_bytes.decode('utf-8')) else: data = json.load(resp) return data
额外补充:有些服务器可能返回deflate格式的压缩内容,你可以把请求头改成Accept-encoding: gzip, deflate,再用zlib模块对应处理deflate的情况,不过大部分场景下gzip已经能覆盖需求了。
内容的提问来源于stack exchange,提问作者Dims
相关产品推荐
相关产品推荐

