Python2.7内存字符串gzip/gunzip工具迁移Python3求助
Python2.7 到 Python3 的 gzip/gunzip 迁移方案(解决 BytesIO/StringIO 适配问题)
在Python3里,字符串(str)和字节(bytes)是严格区分的,这也是你用io.StringIO没解决问题的核心原因——gzip操作的是二进制字节流,必须用BytesIO来处理,而不是处理文本的StringIO。下面是完整的迁移后的代码,我会逐点说明修改逻辑:
修改后的核心代码
from io import BytesIO import gzip import zlib def str_to_gz_str(orig_text_str, mode='wb'): """ @param orig_text_str: Original uncompressed text str @param mode: 'wb' default. 必须是二进制写入模式,因为gzip处理字节流 @return compressed bytes(Python3中压缩结果是字节类型,而非字符串) """ out = BytesIO() # 先把字符串编码成字节,再写入gzip流 with gzip.GzipFile(fileobj=out, mode=mode) as f: f.write(orig_text_str.encode('utf-8')) return out.getvalue() def gz_str_to_str(compressed_bytes): ''' @param compressed_bytes: gzipped bytes(Python3中接收字节类型,而非字符串) @return decompressed string ''' si = BytesIO(compressed_bytes) return gunzip_stream_to_str(si) def gunzip_stream_to_str(gz_stream): ''' decompress gz stream convert to string @param gz_stream: gzipped stream(BytesIO类型的字节流) @return decompressed str ''' unzipped_bytes = b'' # 先拼接字节,最后再解码成字符串 for part in gunzip_stream(gz_stream): unzipped_bytes += part return unzipped_bytes.decode('utf-8') def gunzip_stream(gz_stream): ''' decompress gzipped stream @param gz_stream: src stream that is gzipped(BytesIO类型) @return yield decompressed byte chunks ''' dec = zlib.decompressobj(16+zlib.MAX_WBITS) # gz_stream是BytesIO,迭代出来的chunk是字节类型 for chunk in gz_stream: uz = dec.decompress(chunk) if uz: yield uz
修改点说明
- 导入替换:把
from StringIO import StringIO换成from io import BytesIO,因为我们全程处理的是二进制字节流,而非文本流。 - 字符串转字节:在
str_to_gz_str中,先把输入的orig_text_str用encode('utf-8')转成字节,再写入gzip流——Python3的gzip.GzipFile在二进制模式下只接受字节输入。 - 返回类型调整:压缩后的结果从Python2的“字节字符串”变成Python3的
bytes类型,这是更严谨的类型区分。 - 解压后解码:在
gunzip_stream_to_str中,先拼接解压出的字节片段,最后用decode('utf-8')转成字符串,还原原始文本。 - 模式参数默认值修改:把
mode='w'改成mode='wb',因为gzip在Python3中默认如果用文本模式('w')会要求指定编码,而我们直接用二进制模式更符合gzip的使用场景。
测试代码(适配Python3)
txt_orig = "A Quick Brown fox" txt_gz = str_to_gz_str(txt_orig) # txt_gz现在是bytes类型,打印会显示b'...' txt_decompr = gz_str_to_str(txt_gz) assert(txt_orig == txt_decompr) print("测试通过!")
运行这段测试代码,会成功通过断言,说明压缩和解压的逻辑完全正常。
内容的提问来源于stack exchange,提问作者sky
相关产品推荐
相关产品推荐

