Python pickle调用cPickle?

2024-05-21 09:10:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我对Python还不熟悉。我正在将其他人的代码从Python 2.X修改为3.5。代码通过cPickle加载文件。我将所有“cPickle”事件都改为“pickle”,因为我知道pickle在3.5中取代了cPickle。我得到这个执行错误:

NameError: name 'cPickle' is not defined

相关代码:

import pickle
import gzip
...
def load_data():
    f = gzip.open('../data/mnist.pkl.gz', 'rb')
    training_data, validation_data, test_data = pickle.load(f, fix_imports=True)
    f.close()
    return (training_data, validation_data, test_data)

当另一个函数调用load_data()时,错误出现在pickle.load行中。但是,a)无论cPickle还是cpickle都不再出现在项目的任何源文件中(全局搜索),b)如果我在Python shell中单独运行load_data()中的行,则不会发生错误(但是,我确实收到另一个数据格式错误)。是pickle在调用cPickle,如果是,我如何停止它?

外壳: Python3.5.0 |Python2.4.0(x86_64)|(默认值,2015年10月20日,14:39:26) [通用条款第4.2.1条(苹果公司5577号大楼)]

IDE:IntelliJ 15.0.1、Python 3.5.0、anaconda

不清楚如何进行。感谢任何帮助。谢谢。


Tags: 文件代码nametestimportdata错误training
3条回答

实际上,如果已经从python2.x中选取对象,那么通常可以通过python3.x读取。此外,如果从python3.x中选取了对象,则通常可以通过python2.x读取它们,但前提是它们被转储时protocol设置为2或更低。

Python 2.7.10 (default, Sep  2 2015, 17:36:25) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> x = [1,2,3,4,5]
>>> import math
>>> y = math.sin
>>>     
>>> import pickle 
>>> f = open('foo.pik', 'w') 
>>> pickle.dump(x, f)
>>> pickle.dump(y, f)
>>> f.close()
>>> 
dude@hilbert>$ python3.5
Python 3.5.0 (default, Sep 15 2015, 23:57:10) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> with open('foo.pik', 'rb') as f:
...   x = pickle.load(f)
...   y = pickle.load(f)
... 
>>> x
[1, 2, 3, 4, 5]
>>> y
<built-in function sin>

另外,如果您正在寻找cPickle,现在是_pickle,而不是pickle

>>> import _pickle
>>> _pickle
<module '_pickle' from '/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/lib-dynload/_pickle.cpython-35m-darwin.so'>
>>> 

您还问了如何使用内置的(C++)版本来阻止^ {CD9>}。如果您想使用类对象,可以使用_dump_load,或者使用_Pickler类。困惑的?旧的cPickle现在是_pickle,但是dumploaddumps,和loads都指向_pickle…而_dump_load_dumps,和_loads指向纯python版本。例如:

>>> import pickle
>>> # _dumps is a python function
>>> pickle._dumps
<function _dumps at 0x109c836a8>
>>> # dumps is a built-in (C++)
>>> pickle.dumps
<built-in function dumps>
>>> # the Pickler points to _pickle (C++)
>>> pickle.Pickler 
<class '_pickle.Pickler'>
>>> # the _Pickler points to pickle (pure python)
>>> pickle._Pickler
<class 'pickle._Pickler'>
>>> 

因此,如果不想使用内置版本,那么可以使用pickle._loads等。

在PythonPython3.5中: 用户可以通过以下方式访问cPickle

import _pickle as cPickle

Mike McKerns的学分

看起来您试图加载的pickled数据是由运行在Python 2.7上的程序版本生成的。数据包含对cPickle的引用。

问题在于,Pickle作为序列化格式,假设您的标准库(以及在较小程度上您的代码)不会在序列化和反序列化之间更改布局。它在Python2和3之间做了很多。当这种情况发生时,Pickle没有迁移的路径。

您有权访问生成mnist.pkl.gz的程序吗?如果是,请将其移植到Python 3并重新运行,以重新生成与python3兼容的文件版本。

如果不是这样,则必须编写一个Python 2程序来加载该文件并将其导出为可从Python 3加载的格式(取决于数据的形状,JSON和CSV是常用的选择),然后编写一个python3程序来加载该格式,然后将其转储为python3 pickle。然后可以从原始程序加载Pickle文件。

当然,您真正应该做的是停止在您能够从Python3加载导出格式的地方——并将上述格式用作实际的长期存储格式。

使用Pickle在受信任的程序之间进行短期序列化(加载Pickle相当于在Python VM中运行任意代码)之外的任何操作都是应该积极避免的,尤其是因为您所处的具体情况。

相关问题 更多 >