首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么pickle协议2让我序列化一个打开的文件对象?

为什么pickle协议2让我序列化一个打开的文件对象?
EN

Stack Overflow用户
提问于 2011-08-18 20:28:40
回答 2查看 2.5K关注 0票数 16

考虑一下:

代码语言:javascript
复制
>>> import pickle
>>> thing = open('foobar.txt','w')
>>> pickle.dumps(thing)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/pickle.py", line 1366, in dumps
    Pickler(file, protocol).dump(obj)
  File "/usr/lib/python2.6/pickle.py", line 224, in dump
    self.save(obj)
  File "/usr/lib/python2.6/pickle.py", line 306, in save
    rv = reduce(self.proto)
  File "/usr/lib/python2.6/copy_reg.py", line 70, in _reduce_ex
    raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle file objects

看起来是完全合理的--当然我不能处理一个打开的文件句柄。但是:

代码语言:javascript
复制
>>> pickle.dumps(thing, 2)
'\x80\x02c__builtin__\nfile\nq\x00)\x81q\x01.'
>>> pickle.loads(pickle.dumps(thing, 2))
<closed file '<uninitialized file>', mode '<uninitialized file>' at 0x7ff3c078>

显然我可以清理一个打开的文件,但不是很有用。

这是故意的吗?它掩盖了我代码中的一个bug,我错误地酸洗了一个拥有文件的对象。在某些情况下,该对象还持有pyodbc游标,结果相同。

我在PEP 307上看不到任何关于它的东西。这只是一个疏忽,或者是我遗漏了一些重要的事情,即使在使用协议2进行酸洗时,也可以让我得到我想要的异常?

我使用的是Python 2.6.5。我知道,我知道,但这是我的发行版附带的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-08-18 20:43:21

Python Wiki上,它说

您不能选取打开的文件对象、网络连接或数据库连接。仔细想想,这是有道理的-- pickle不能在取消pickle对象的pickle时使文件对象的连接存在,并且创建该连接的过程超出了pickle可以自动为您做的事情。如果您确实想要剔除具有导致问题的属性的对象,请查看__getstate____setstate____getinitargs__的剔除文档--使用这些文档可以排除有问题的属性。

然而,我发现了this bug report,它表明您实际上可以 pickle文件对象。这看起来确实是无意的。在Python 3.2中已经修复了这个问题。

如果你想防止这种情况的发生,你可以看看你是否可以将这个补丁改编到Python2.6。否则,你只需要小心你腌制的东西。

票数 10
EN

Stack Overflow用户

发布于 2014-07-18 02:34:35

如果你正在寻找更好的行为,你可以使用dill...它不会序列化类似文件的对象,但知道如何序列化文件句柄。其行为是,如果文件存在,dill会将反序列化的文件句柄指向它……如果文件不存在,那么文件句柄将被关闭。

代码语言:javascript
复制
Python 2.7.8 (default, Jul  3 2014, 05:59:29) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>>        
>>> thing = open('foobar.txt', 'w')
>>> thing
<open file 'foobar.txt', mode 'w' at 0x10e3c2c00>
>>> dill.loads(dill.dumps(thing))
<open file 'foobar.txt', mode 'w' at 0x10e3c2c90>
>>> 

在这里获取dillhttps://github.com/uqfoundation

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7107409

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档