在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 "<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正在生成的主要数据块的每一侧包含几个字符。然后我尝试将其修剪为zlibs输出并将其放入zlib.decompress。我的问题是它读取文件并将“\ x04”之类的内容解释为四个字符而不是一个字符。很多测试和搜索后来我找不到一种方法来使pickle加载文件,或者让python识别这些代码所以我可以通过zlib。
所以我的问题是: 如何使用Python3.1恢复原始数据?
我很乐意让我的客户安装Python2.5并手动完成,但这是不可能的。
非常感谢您的协助!
答案 0 :(得分:12)
问题在于Python 3正在尝试将pickled Python 2字符串转换为str
对象,而实际需要它为bytes
。它使用ascii
编解码器执行此操作,该编解码器不支持所有256个8位字符,因此您将获得异常。
您可以使用latin-1
编码(支持所有256个字符),然后将字符串编码回bytes
来解决此问题:
s = pickle.load(f, encoding='latin1')
b = s.encode('latin1')
print(zlib.decompress(b))
答案 1 :(得分:0)
Python 3区分二进制数据和字符串。 Pickle需要二进制数据,但您将文件作为文本打开。解决方案是使用:
open(file_name, 'wb')