Python pickle 调用 cPickle?
Python pickle calls cPickle?
我是 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) 如果我 运行 load_data()
分别在 Python shell 中(但是,我确实遇到了另一个数据格式错误)。 pickle
是否在调用 cPickle
,如果是,我该如何停止它?
Shell:
Python 3.5.0 |蟒蛇 2.4.0 (x86_64)| (默认,2015 年 10 月 20 日,14:39:26)
[GCC 4.2.1 (Apple Inc. build 5577)] 在达尔文
IDE:IntelliJ 15.0.1,Python 3.5.0,蟒蛇
不清楚如何进行。任何帮助表示赞赏。谢谢。
您尝试加载的 pickled 数据似乎是由 运行ning 在 Python 2.7 上的程序版本生成的。数据是包含对 cPickle
.
的引用的内容
问题在于,作为一种序列化格式,Pickle 假定您的标准库(以及在较小程度上您的代码)不会在序列化和反序列化之间更改布局。它在 Python 2 和 3 之间做了很多次。当发生这种情况时,Pickle 没有迁移路径。
您是否有权访问生成 mnist.pkl.gz
的程序?如果是这样,将其移植到 Python 3 并重新 运行 它以重新生成文件的 Python 3 兼容版本。
如果没有,您将不得不编写一个 Python 2 程序来加载该文件并将其导出为可以从 Python 3 加载的格式(取决于您的形状)数据,JSON 和 CSV 是流行的选择),然后编写一个 Python 3 程序加载该格式,然后将其转储为 Python 3 pickle。然后您可以从您的原始程序加载该 Pickle 文件。
当然,您 真正 应该做的是在您能够从 Python 3 加载导出的格式时停止,并使用上述格式作为您实际的长期存储格式。
将 Pickle 用于 受信任的 程序之间的短期序列化以外的任何事情(加载 Pickle 相当于 运行 在您的 Python VM 中使用任意代码) 是你应该积极避免的事情,尤其是因为你发现自己所处的确切情况。
实际上,如果您从 python2.x
中 pickle 了对象,那么通常可以被 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'>
>>>
您还询问了如何阻止 pickle
使用内置 (C++) 版本。您可以使用 _dump
和 _load
或 _Pickler
class(如果您喜欢使用 class 对象)来执行此操作。使困惑?旧的 cPickle
现在是 _pickle
,但是 dump
、load
、dumps
和 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
之类的。
在 Anaconda Python3.5 中:
可以访问 cPickle 作为
import _pickle as cPickle
感谢 Mike McKerns
这绕过了技术问题,但该文件的 py3 版本可能名为 mnist_py3k.pkl.gz 如果是这样,请尝试打开该文件。
github 中有一个代码可以做到这一点:https://gist.github.com/rebeccabilbro/2c7bb4d1acfbcdcf9156e7b9b7577cba
我试过了,很有效。您只需要指定编码,在本例中为 'latin1':
pickle.load(open('mnist.pkl','rb'), encoding = 'latin1')
我是 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) 如果我 运行 load_data()
分别在 Python shell 中(但是,我确实遇到了另一个数据格式错误)。 pickle
是否在调用 cPickle
,如果是,我该如何停止它?
Shell: Python 3.5.0 |蟒蛇 2.4.0 (x86_64)| (默认,2015 年 10 月 20 日,14:39:26) [GCC 4.2.1 (Apple Inc. build 5577)] 在达尔文
IDE:IntelliJ 15.0.1,Python 3.5.0,蟒蛇
不清楚如何进行。任何帮助表示赞赏。谢谢。
您尝试加载的 pickled 数据似乎是由 运行ning 在 Python 2.7 上的程序版本生成的。数据是包含对 cPickle
.
问题在于,作为一种序列化格式,Pickle 假定您的标准库(以及在较小程度上您的代码)不会在序列化和反序列化之间更改布局。它在 Python 2 和 3 之间做了很多次。当发生这种情况时,Pickle 没有迁移路径。
您是否有权访问生成 mnist.pkl.gz
的程序?如果是这样,将其移植到 Python 3 并重新 运行 它以重新生成文件的 Python 3 兼容版本。
如果没有,您将不得不编写一个 Python 2 程序来加载该文件并将其导出为可以从 Python 3 加载的格式(取决于您的形状)数据,JSON 和 CSV 是流行的选择),然后编写一个 Python 3 程序加载该格式,然后将其转储为 Python 3 pickle。然后您可以从您的原始程序加载该 Pickle 文件。
当然,您 真正 应该做的是在您能够从 Python 3 加载导出的格式时停止,并使用上述格式作为您实际的长期存储格式。
将 Pickle 用于 受信任的 程序之间的短期序列化以外的任何事情(加载 Pickle 相当于 运行 在您的 Python VM 中使用任意代码) 是你应该积极避免的事情,尤其是因为你发现自己所处的确切情况。
实际上,如果您从 python2.x
中 pickle 了对象,那么通常可以被 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'>
>>>
您还询问了如何阻止 pickle
使用内置 (C++) 版本。您可以使用 _dump
和 _load
或 _Pickler
class(如果您喜欢使用 class 对象)来执行此操作。使困惑?旧的 cPickle
现在是 _pickle
,但是 dump
、load
、dumps
和 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
之类的。
在 Anaconda Python3.5 中: 可以访问 cPickle 作为
import _pickle as cPickle
感谢 Mike McKerns
这绕过了技术问题,但该文件的 py3 版本可能名为 mnist_py3k.pkl.gz 如果是这样,请尝试打开该文件。
github 中有一个代码可以做到这一点:https://gist.github.com/rebeccabilbro/2c7bb4d1acfbcdcf9156e7b9b7577cba
我试过了,很有效。您只需要指定编码,在本例中为 'latin1':
pickle.load(open('mnist.pkl','rb'), encoding = 'latin1')