在Python 3.1中解压缩Python 2.5中pickle的数据并使用zlib

10 投票
2 回答
6278 浏览
提问于 2025-04-16 07:37

在Python 2.5中,我用这段代码存储数据:

def GLWriter(file_name, string):
   import cPickle
   import zlib
   data = zlib.compress(str(string))
   file = open(file_name, 'w')
   cPickle.dump(data, file)

这个方法很好用,我可以通过反向操作来读取这些数据。数据不需要特别安全,只要人眼看不懂就行。如果我把“test”放进去,然后打开它生成的文件,内容看起来是这样的:

S'x\x9c+I-.\x01\x00\x04]\x01\xc1'
p1
.

由于各种原因,我们现在必须使用Python 3.1,并且需要编写一些代码来读取这些数据文件。

Pickle不再接受字符串输入,所以我必须用“rb”模式打开文件。当我这样做并尝试用pickle.load(file)来打开它时,我遇到了这个错误:

File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line 1365, in load
   encoding=encoding, errors=errors).load()
UnicodeDecodingError: 'ascii' codec can't decode byte 0x9c in position 1: ordinal not in range(128)

我想也许无法用pickle打开这个文件,于是开始做一些研究,发现pickle其实只是把主数据块的两边包裹了一些字符,而这些数据是zlib生成的。然后我尝试把它缩减到zlib的输出,并用zlib.decompress处理。但是我遇到的问题是,它读取文件时把像“\x04”这样的内容当成四个字符,而不是一个字符。经过很多测试和搜索,我还是找不到办法让pickle加载这个文件,或者让Python识别这些代码,以便我可以通过zlib处理。

所以我的问题是: 我该如何用Python 3.1恢复原始数据?

我很想请我的客户安装Python 2.5手动操作,但这不太可能。

非常感谢你的帮助!

2 个回答

0

Python 3 区分了二进制数据和字符串。Pickle 需要的是二进制数据,但你打开文件时用的是文本模式。解决这个问题的方法是使用:

open(file_name, 'wb')
13

问题在于,Python 3 正在尝试把用 Python 2 保存的字符串转换成 str 对象,但实际上你需要的是 bytes 类型。Python 3 使用的是 ascii 编码,这种编码不支持所有 256 个 8 位字符,所以你会遇到错误。

你可以通过使用 latin-1 编码来解决这个问题(这种编码支持所有 256 个字符),然后再把字符串转换回 bytes 类型:

s = pickle.load(f, encoding='latin1')
b = s.encode('latin1')
print(zlib.decompress(b))

撰写回答