49

当我尝试加载使用 cPickle 转储的内容时,我收到错误消息:

ValueError: insecure string pickle

转储和加载工作都在同一台计算机上完成,因此使用相同的操作系统:Ubuntu 8.04。

我该如何解决这个问题?

4

10 回答 10

88

“在全世界每天使用数十亿次的功能中,比 Python 本身从未观察到的错误更有可能”:这总是让我惊讶于人们在这些论坛中的交流方式。

解决此问题的一种简单方法是忘记关闭用于转储数据结构的流。我已经做了

>>> out = open('xxx.dmp', 'w')
>>> cPickle.dump(d, out)
>>> k = cPickle.load(open('xxx.dmp', 'r'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: insecure string pickle

这就是我一开始来这里的原因,因为我看不出我做错了什么。
然后我真的想到了,而不是只是来这里,并意识到我应该这样做:

>>> out = open('xxx.dmp', 'w')
>>> cPickle.dump(d, out)
>>> out.close() # close it to make sure it's all been written
>>> k = cPickle.load(open('xxx.dmp', 'r'))

容易忘记。不需要人们被告知他们是白痴。

于 2012-11-15T10:25:42.770 回答
13

由于打开模式“rb”,我在 Python 2.7 中遇到了这个错误:

    with open(path_to_file, 'rb') as pickle_file:
        obj = pickle.load(pickle_file)

所以,对于 Python 2 'mode' 应该是 'r'

另外,我想知道 Python 3 不支持 Python 2 的 pickle 格式,如果你尝试加载在 Python 2 中创建的 pickle 文件,你会得到:

pickle.unpicklingerror: the string opcode argument must be quoted
于 2015-08-30T07:23:12.020 回答
9

检查这个线程。彼得奥滕 说:

腐烂的泡菜。如果转储中的字符串不以“或”开头和结尾,则会引发错误。

并展示了一种重现这种“腐败”的简单方法。Steve Holden 在后续文章中提出了导致问题的另一种方法是不匹配 'rb' 和 'wb' (但在 Python 2 和 Linux 上,该特定错误应该被忽视)。

于 2009-11-17T06:10:53.737 回答
7

你对 和 之间的数据做了dump()什么load()?将腌制数据存储在以文本模式(在 Windows 上)打开的文件中或以二进制数据(VARCHAR、某些数据库中的 TEXT 列、某些键值存储)无法正常工作的方式存储在数据库存储中是很常见的错误。尝试比较您传递到存储并立即从中检索的腌制数据。

于 2009-11-17T14:54:34.380 回答
7

如果有人在使用时遇到此错误youtube-dl,则此问题已修复:https ://github.com/rg3/youtube-dl/issues/7172#issuecomment-242961695

Richiecannizzo 评论于 8 月 28 日

brew install libav
应该立即在 mac 上修复它或

sudo apt-get install libav
#在Linux上

于 2016-12-15T01:37:06.943 回答
6

如果您的泡菜很大( Python 问题 #11564 ) ,python 2(和早期版本的 python 3)也可能出现此错误:

Python 2.7.11 |Anaconda custom (64-bit)| (default, Dec  6 2015, 18:08:32) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
>>> import cPickle as pickle
>>> string = "X"*(2**31)
>>> pp = pickle.dumps(string)
>>> len(pp)
2147483656
>>> ss = pickle.loads(pp)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: insecure string pickle

通过在 python 3.4 ( PEP 3154 )中引入 pickle 协议 4 解决了这个限制。不幸的是,此功能尚未向后移植到 python 2,并且可能永远不会。如果这是您的问题,并且您需要使用 python 2 泡菜,那么您能做的最好的事情就是减小泡菜的大小,例如,不是酸洗 a ,而是list将元素单独腌制成 alist泡菜。

于 2016-10-18T18:44:03.850 回答
4

在 Windows 上用 python 创建并在 linux 上用 python 重新加载的文件也存在同样的问题。解决方案:在 linux 中阅读之前对文件进行 dos2unix:作为一种魅力!

于 2014-08-28T08:56:29.633 回答
3

Python ValueError: insecure string pickle以不同的方式收到了信息。

对我来说,它发生在base64对二进制文件进行编码并通过urllib2套接字之后。

最初我正在包装这样的文件

with open(path_to_binary_file) as data_file:
    contents = data_file.read() 
filename = os.path.split(path)[1]

url = 'http://0.0.0.0:8080/upload'
message = {"filename" : filename, "contents": contents}
pickled_message = cPickle.dumps(message)
base64_message = base64.b64encode(pickled_message)
the_hash = hashlib.md5(base64_message).hexdigest()

server_response = urllib2.urlopen(url, base64_message)

但是在服务器上,某些二进制文件的哈希值一直不同

decoded_message = base64.b64decode(incoming_base64_message)
the_hash = hashlib.md5(decoded_message).hexdigest()

并且 unpickling 给出了insecure string pickle信息

cPickle.loads(decoded_message)

但成功

对我有用的是使用urlsafe_b64encode()

base64_message = base64.urlsafe_b64encode(cPickle.dumps(message))

并使用解码

base64_decoded_message = base64.urlsafe_b64decode(base64_message)

参考

http://docs.python.org/2/library/base64.html

https://www.rfc-editor.org/rfc/rfc3548.html#section-3

于 2014-02-11T17:45:05.623 回答
1

这就是发生在我身上的事情,可能只是一小部分人,但我还是想把它放在这里,为他们:

解释器(Python3)会给你一个错误,说它要求输入文件流以字节为单位,而不是字符串,你可能已经将打开模式参数从'r'更改为'rb',现在它是告诉您字符串已损坏,这就是您来这里的原因。

对于这种情况,最简单的选择是安装 Python2(您可以安装 2.7),然后在 Python 2.7 环境中运行您的程序,因此它可以毫无问题地解压您的文件。基本上,我浪费了很多时间来扫描我的字符串,看看它是否确实损坏了,而我所要做的就是将打开文件的模式从 rb 更改为 r,然后使用 Python2 解压文件。所以我只是把这些信息放在那里。

于 2016-08-02T19:06:20.277 回答
0

我早些时候遇到过这个问题,找到了这个线程,并假设我对其中几个答案中提到的文件关闭问题免疫,因为我使用了一个with语句:

with tempfile.NamedTemporaryFile(mode='wb') as temp_file:
    pickle.dump(foo, temp_file)

    # Push file to another machine
    _send_file(temp_file.name)

但是,由于我从内部推送临时文件,该with文件仍未关闭,因此我推送的文件被截断。这导致在insecure string pickle读取远程计算机上的文件的脚本中出现相同的错误。

对此有两个潜在的修复:保持文件打开并强制刷新:

with tempfile.NamedTemporaryFile(mode='wb') as temp_file:
    pickle.dump(foo, temp_file)
    temp_file.flush()

    # Push file to another machine
    _send_file(temp_file.name)

或者在对其进行任何操作之前确保文件已关闭:

file_name = ''
with tempfile.NamedTemporaryFile(mode='wb', delete=False) as temp_file:
    file_name = temp_file.name
    pickle.dump(foo, temp_file)

# Push file to another machine
_send_file(file_name)
于 2018-04-06T14:14:42.793 回答