当我尝试加载使用cPickle转储的内容时,收到错误消息:
ValueError: insecure string pickle
转储和加载工作都在同一台计算机上完成,因此操作系统相同:Ubuntu 8.04。
我怎么能解决这个问题?
答案 0 :(得分:86)
“比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'))
容易忘记。不需要让人们被告知他们是白痴。
答案 1 :(得分:9)
由于开放模式'rb',我在Python 2.7中遇到此错误:
with open(path_to_file, 'rb') as pickle_file:
obj = pickle.load(pickle_file)
因此,对于Python 2'模式'应该是'r'
另外,我想知道Python 3不支持Python 2的pickle格式,如果你试图加载在Python 2中创建的pickle文件,你会得到:
pickle.unpicklingerror: the string opcode argument must be quoted
答案 2 :(得分:8)
检查this thread。彼得奥顿说:
腐败的泡菜。错误是 如果转储中有字符串,则引发 不是以“或”开头和结尾。
并显示了一种简单的方法来重现这种“腐败”。后续帖子中的Steve Holden建议另一种导致问题的方法是使'rb'和'wb'不匹配(但在Python 2和Linux上,特定错误应该忽略不计)。
答案 3 :(得分:7)
您对dump()
和load()
之间的数据做了什么?将pickle数据存储在以文本模式(在Windows上)或数据库存储中打开的文件中的方式是非常常见的错误,因为二进制数据无法正常工作(某些数据库中的VARCHAR,TEXT列,某些键值存储)。尝试比较传递给存储并立即从中检索的腌制数据。
答案 4 :(得分: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
#on linux
答案 5 :(得分:6)
如果你的pickle很大(Python Issue #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 pickle,你可以做的最好的事情就是减少pickle的大小,例如,而不是腌制list
,将元素单独挑选到list
泡菜。
答案 6 :(得分:4)
在Windows上用python制作的文件同样存在问题,并在linux上重新加载python。 解决方案:在linux上阅读文件之前的dos2unix:作为一个魅力!
答案 7 :(得分: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)
<强>参考强>
答案 8 :(得分:1)
这就是发生在我身上的事情,可能只是一小部分人口,但我想把它放在这里,对他们来说:
解释器(Python3)会给你一个错误,说它需要输入文件流是以字节为单位而不是字符串,你可能已经将开放模式参数从'r'更改为'rb',并且现在它告诉你字符串已损坏,这就是你来这里的原因。
这种情况最简单的选择是安装Python2(你可以安装2.7)然后用Python 2.7环境运行你的程序,这样就可以毫发问题地解开你的文件。基本上我浪费了很多时间来扫描我的字符串,看看它是否确实已经损坏,我所要做的就是将文件从rb更改为r,然后使用Python2来解开文件。所以我只是把这些信息放在那里。
答案 9 :(得分: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)