ImportError:没有名为copy_reg pickle的模块

时间:2009-02-17 10:42:59

标签: python pickle

我正在尝试在MySQL数据库中取消存储为blob的对象。我手动生成并将pickled对象存储在数据库中,但是当我尝试unpickle对象时,我得到以下相当神秘的异常:

ImportError:没有名为copy_reg的模块

关于为什么会发生这种情况的任何想法?

复制方法

注意:必须在Windows PC上执行第1步,在Linux PC上执行步骤3和4。

1)在Windows PC上:

file = open("test.txt", "w")
thing = {'a': 1, 'b':2}
cPickle.dump(thing, file)

2)手动将text.txt的内容插入到linux上运行的MySQL数据库的blob字段中

3)在Linux机器上运行的Python中,从MySQL中获取列的内容

4)假设你将blob列的内容放入一个名为data的变量中,试试这个:

cPickle.loads(rawString)

9 个答案:

答案 0 :(得分:23)

这似乎可能是由我导出pickle对象的方法引起的。

This bug report认为可以通过导出到以二进制模式写入的文件来解决我的问题。我现在就开始尝试,看看这是否解决了我的问题。

更新:这有效。解决方案是确保将pickle对象导出到以二进制模式打开的文件,即使您使用的是默认协议0(通常称为“text”)

根据所讨论的orignal示例更正代码:

file = open("test.txt", 'wb')
thing = {'a': 1, 'b':2}
cPickle.dump(thing, file)

答案 1 :(得分:15)

另外,简单地在(windows创建的)pickle文件上运行dos2unix(在linux下)解决了我的问题。 (没试过开放模式'wb'的事情。) 丹

答案 2 :(得分:3)

只是一个交互式python会话,以显示您不需要任何特定代码来解决此问题:

在Windows机器上做这样的事情

Python 2.4.1 (#65, Mar 30 2005, 09:13:57) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle, re
>>> empty_string = re.compile("^$")
>>> pickle.dump([empty_string,1,1.23,'abc'], file('m:/mario/test-b.dump','wb'))
>>> pickle.dump([empty_string,1,1.23,'abc'], file('m:/mario/test-t.dump','wt'))
>>> 

然后尝试从linux框中检索数据

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> pickle.load(file('/home/mario/.gvfs/transfer on 192.168.0.4/mario/test-b.dump'))
/usr/lib/python2.6/pickle.py:1124: DeprecationWarning: The sre module is deprecated, please import re.
  __import__(module)
[<_sre.SRE_Pattern object at 0xb7d42420>, 1, 1.23, 'abc']
>>> pickle.load(file('/home/mario/.gvfs/transfer on 192.168.0.4/mario/test-t.dump'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/pickle.py", line 1370, in load
    return Unpickler(file).load()
  File "/usr/lib/python2.6/pickle.py", line 858, in load
    dispatch[key](self)
  File "/usr/lib/python2.6/pickle.py", line 1090, in load_global
    klass = self.find_class(module, name)
  File "/usr/lib/python2.6/pickle.py", line 1124, in find_class
    __import__(module)
ImportError: No module named sre
>>> 
如果您只是在挑选基础类型,错误消息可能会更加混乱。这是我使用列表[12, 1.2, '']得到的:

ValueError: insecure string pickle

答案 3 :(得分:1)

这里发生的另一件事是,在将pickle倾倒到它之后,你似乎没有关闭文件。通过不关闭文件,有时可能会导致此处报告的错误(无论是在Windows计算机上还是其他方式)。

答案 4 :(得分:1)

如其他答案所述

dos2unix originalPickle.file outputPickle.file

或者使用如下所示的tr命令(删除回车和ctrl-z)

  tr -d '\15\32' < originalPickle.file > outputPickle.file

或使用awkgawknawk,如果旧版本)

  awk '{ sub("\r$", ""); print }' originalPickle.file > outputPickle.file

如果您可以在linux中重新创建pickle文件,请使用它。

答案 5 :(得分:1)

我的问题:

with open('model.pkl', 'rb') as f:
    subsection_struct_model = pickle.load(f)

当我从Windows中获取model.pkl时,在我的mac机中运行此代码,此问题即将出现

解决:

dos2unix model.pkl 

还可以!

答案 6 :(得分:0)

pickle加载可能与python脚本的位置不同。有时,目录会根据您的应用程序而更改。在加载pickle之前,打印一个os.getcwd()来制定解决方案。

答案 7 :(得分:0)

之所以发生这种情况,是因为在Windows中,新行符号存储为“ \ r \ n”,而在Linux中,新行符号存储为“ \ n”,因此,您应该逐行读取pickle文件,替换为“ \ r \ n“和” \ n“,然后将其写回到文件中。

与dos2unix方法将跳过二进制文件不同,这也适用于二进制pickle文件。

代码很简单:

#run this code on Linux platform

DIR="your/dir/to/file"

pickle.load(open(DIR,"rb"))
# ImportError: No module named copy_reg pickle

a=open(DIR,"rb").readlines() #read pickle file line by line

a=map(lambda x:x.replace("\r\n","\n"),a) # replace \r\n with \n

with open(DIR,"wb") as j: #write back to file in binary mode
    for i in a:
        j.write(i)         
pickle.load(open(DIR,"rb")) 
#Now it works well

此外,您可以使用普通写入模式,只需将“ wb”更改为“ w”,将“ rb”更改为“ e”。

答案 8 :(得分:0)

我遇到了这个问题,因为git更改了 Windows上的行尾。

我通过在我的仓库中添加一个.gitattributes文件来解决了这个问题:

# Pickle files (for testing) should always have UNIX line endings. 
*.pkl text eol=lf

另请参阅https://github.com/actions/checkout/issues/135