【问题标题】:Different behaviour for io in pickle with string content带有字符串内容的泡菜中 io 的不同行为
【发布时间】:2014-12-04 11:03:20
【问题描述】:

在处理腌制数据时,我遇到了 io.open__builtin__.open 的不同行为。考虑以下简单示例:

import pickle

payload = 'foo'
fn = 'test.pickle'

pickle.dump(payload, open(fn, 'w'))
a = pickle.load(open(fn, 'r'))

这按预期工作。但是在这里运行这段代码:

import pickle
import io

payload = 'foo'
fn = 'test.pickle'

pickle.dump(payload, io.open(fn, 'w'))
a = pickle.load(io.open(fn, 'r'))

提供以下 Traceback:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "D:\WinPython-32bit-2.7.8.1\python-2.7.8\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 580, in runfile
    execfile(filename, namespace)
  File "D:/**.py", line 15, in <module>
    pickle.dump(payload, io.open(fn, 'w'))
  File "D:\WinPython-32bit-2.7.8.1\python-2.7.8\lib\pickle.py", line 1370, in dump
    Pickler(file, protocol).dump(obj)
  File "D:\WinPython-32bit-2.7.8.1\python-2.7.8\lib\pickle.py", line 224, in dump
    self.save(obj)
  File "D:\WinPython-32bit-2.7.8.1\python-2.7.8\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "D:\WinPython-32bit-2.7.8.1\python-2.7.8\lib\pickle.py", line 488, in save_string
    self.write(STRING + repr(obj) + '\n')
TypeError: must be unicode, not str

由于我想与未来兼容,我该如何规避这种不当行为?或者,我在这里还有什么问题?

我在转储带有字符串类型键的字典时偶然发现了这一点。

我的python版本是: '2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)]'

【问题讨论】:

    标签: python-2.7 unicode io pickle python-unicode


    【解决方案1】:

    差异并不令人惊讶,因为io.open()明确在使用文本模式时处理 Unicode 字符串。文档对此非常清楚:

    注意:由于该模块主要是为 Python 3.x 设计的,因此您必须注意,本文档中所有“字节”的使用均指 str 类型(其中bytes 是一个别名),所有“文本”的使用都是指unicode 类型。此外,这两种类型在 io API 中不可互换。

    Python 区分以二进制和文本模式打开的文件,即使底层操作系统没有。以二进制模式打开的文件(包括 mode 参数中的'b')返回内容为bytes 对象,无需任何解码。在文本模式下(默认或当't' 包含在mode 参数中时),文件的内容作为unicode 字符串返回,这些字节首先使用平台解码-依赖编码或使用指定的编码(如果给定)。

    您需要以二进制模式打开文件。事实上,它在没有内置 open() 的情况下工作,实际上是运气多于智慧;如果你的泡菜包含\n 和/或\r 字节的数据,泡菜加载很可能会失败。 Python 2 默认的 pickle 恰好是一个文本协议,但输出仍应被视为二进制。

    在所有情况下,写入pickle数据时,使用二进制模式:

    pickle.dump(payload, open(fn, 'wb'))
    a = pickle.load(open(fn, 'rb'))
    

    pickle.dump(payload, io.open(fn, 'wb'))
    a = pickle.load(io.open(fn, 'rb'))
    

    【讨论】:

      猜你喜欢
      • 2011-02-27
      • 2014-12-19
      • 1970-01-01
      • 2013-04-09
      • 1970-01-01
      • 2014-07-15
      • 1970-01-01
      • 2011-10-14
      • 2023-03-11
      相关资源
      最近更新 更多