web-dev-qa-db-ja.com

ValueError:安全でない文字列のピクル

CPickleを使用してダンプしたものを読み込もうとすると、エラーメッセージが表示されます。

ValueError: insecure string pickle

ダンプとロードの両方の作業は同じコンピューターで行われます。したがって、同じOS:Ubuntu 8.04です。

どうすればこの問題を解決できますか?

46
Peter Long

「Pythonそれ自体が世界中で1日に数十億回使用されている機能において、それ自体が観察されていないバグよりもはるかに高い可能性があります。」: 。

この問題を解決する簡単な方法の1つは、データ構造のダンプに使用しているストリームを閉じることを忘れることです。今やりました

>>> 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'))

忘れやすい。馬鹿だと言われる必要はありませんでした。

86
Allan Ramsay

私はPython 2.7でオープンモード「rb」のためにこのエラーを受け取りました:

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

したがって、Python 2 'mode'は 'r'である必要があります

また、Python 3はPython 2のpickle形式をサポートしておらず、作成されたpickleファイルをロードしようとする場合に備えてin Python 2が得られます:

pickle.unpicklingerror: the string opcode argument must be quoted
9
Oleg Neumyvakin

このスレッド を確認してください。ピーター・オッテン氏:

壊れた漬物。ダンプ内の文字列の開始と終了の両方が「または」でない場合、エラーが発生します。

そして、そのような「破損」を再現する簡単な方法を示しています。フォローアップ記事のSteve Holdenは、問題を引き起こす別の方法は、「rb」と「wb」の不一致であることを示唆しています(ただし、Python 2およびLinuxでは特定の間違いが通過するはずです気付かれない)。

8
Alex Martelli

dump()load()の間のデータで何をしていますか?バイナリデータ(一部のデータベースのVARCHAR、TEXT列、一部のキーと値のストレージ)に対して正しく動作しない方法で、テキストモード(Windows)で開かれたファイルまたはデータベースストレージにピクルスされたデータを保存することは非常に一般的なエラーです。ストレージに渡してすぐに取得したピクルスデータを比較してみてください。

7
Denis Otkidach

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

7
Pysis

このエラーは、ピクルが大きい場合、python 2(およびpython 3の初期バージョン)でも発生する可能性があります( Python Issue#11564 ):

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をpickleする代わりに、要素を個別にpickle listのピクルス。

6
Paul Price

pythonで作成され、Linuxではpythonでリロードされたファイルに関する同じ問題。魅力として!

4
am_technix

別の方法で_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()
_

そして、ピッキング解除は_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
HeyWatchThis

これは私に起こったことであり、人口の小さなセクションかもしれませんが、それでも彼らのためにここに出したいです:

インタープリター(Python3)は、入力ファイルストリームが文字列ではなくバイト単位である必要があるというエラーを表示し、オープンモード引数を 'r'から 'rb'に変更した可能性があります。文字列が壊れているとあなたに伝え、それがあなたがここに来た理由です。

そのような場合の最も簡単なオプションは、Python2をインストールし(2.7をインストールできます)、Python 2.7環境でプログラムを実行することです。したがって、問題なくファイルのピクルを外します。ファイルを開くモードをrbからrに変更し、Python2を使用してファイルのピクルを外すだけで文字列をスキャンして、実際に破損していないかどうかを確認しました。

1
Arijit

私は以前にこれに遭遇し、このスレッドを見つけ、withステートメントを使用していたので、これらの回答のいくつかで言及されたファイルクローズの問題の影響を受けないと仮定しました。

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

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

ただし、一時ファイルをinsidewithからプッシュしていたため、ファイルはまだ閉じられていなかったため、プッシュしていたファイルは切り捨てられました。これにより、同じinsecure string pickleリモートマシン上のファイルを読み取るスクリプトのエラー。

これに対する2つの潜在的な修正:ファイルを開いたままにし、フラッシュを強制します。

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)
0
0x5453