ValueError:不安全的字符串pickle

时间:2009-11-17 05:39:44

标签: python pickle

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

ValueError: insecure string pickle

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

我怎么能解决这个问题?

10 个答案:

答案 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)

<强>参考

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

https://tools.ietf.org/html/rfc3548.html#section-3

答案 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)