web-dev-qa-db-ja.com

Python pickleはcPickleを呼び出しますか?

私はPythonを初めて使用します。他の人のコードをPython 2.Xから3.5に適合させています。コードはcPickleを介してファイルをロードします。3.5でpickleがcPickleに取って代わったことを理解しているので、すべての「cPickle」オカレンスを「pickle」に変更しました。 。この実行エラーが発生します:

_NameError: name 'cPickle' is not defined
_

関連コード:

_import pickle
import gzip
...
def load_data():
    f = gzip.open('../data/mnist.pkl.gz', 'rb')
    training_data, validation_data, test_data = pickle.load(f, fix_imports=True)
    f.close()
    return (training_data, validation_data, test_data)
_

load_data()が別の関数によって呼び出されると、_pickle.load_行でエラーが発生します。ただし、a)cPicklecpickleもプロジェクト内のどのソースファイルにも表示されなくなり(グローバルに検索)、b)load_data() Pythonシェルで個別に(ただし、別のデータ形式エラーが発生します)。picklecPickleを呼び出していますか?その場合はどうすればよいですか?やめますか?

シェル:Python 3.5.0 | Anaconda 2.4.0(x86_64)|(デフォルト、2015年10月20日、14:39:26)[GCC 4.2.1(Apple Inc.ビルド5577)]ダーウィンで

IDE:IntelliJ 15.0.1、Python 3.5.0、anaconda

続行する方法が不明です。助けていただければ幸いです。ありがとう。

10
Ron Cohen

ロードしようとしているpickle化されたデータは、Python 2.7で実行されていたプログラムのバージョンによって生成されたようです。データには、cPickleへの参照が含まれています。

問題は、Pickleがシリアル化形式として、標準ライブラリ(および程度は少ないがコード)がシリアル化と逆シリアル化の間でレイアウトを変更しないことを前提としていることです。 Python 2と3の間で、多くのことを行いました。その場合、Pickleには移行のパスがありません。

_mnist.pkl.gz_を生成したプログラムにアクセスできますか?その場合は、それをPython 3に移植し、再実行してPython 3互換バージョンのファイルを再生成します。

そうでない場合は、そのファイルをロードし、Python 3(依存する)からロードできる形式にエクスポートするPython 2プログラムを作成する必要があります。データの形状については、JSONとCSVが一般的な選択肢です)、次にPython 3プログラムを作成し、その形式をロードして、Python 3 pickle 。その後、元のプログラムからそのPickleファイルをロードできます。

もちろん、あなたがすべきこと本当には、エクスポートされたフォーマットをPython 3-)からロードする能力がある時点で停止し、前述のフォーマットを実際の長期保存形式。

trustedプログラム間の短期シリアル化以外にPickleを使用する(Pickleをロードすることは、Python VM)で任意のコードを実行することと同等です)は積極的に避ける必要があります。とりわけ、あなたが自分自身を見つけた正確なケースのためです。

4
Max Noel

実際、_python2.x_からオブジェクトをピクルス化した場合、通常は_python3.x_で読み取ることができます。また、_python3.x_からオブジェクトをピクルした場合、それらは通常_python2.x_で読み取ることができますが、protocolを_2_以下に設定してダンプした場合に限ります。

_Python 2.7.10 (default, Sep  2 2015, 17:36:25) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> x = [1,2,3,4,5]
>>> import math
>>> y = math.sin
>>>     
>>> import pickle 
>>> f = open('foo.pik', 'w') 
>>> pickle.dump(x, f)
>>> pickle.dump(y, f)
>>> f.close()
>>> 
dude@hilbert>$ python3.5
Python 3.5.0 (default, Sep 15 2015, 23:57:10) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> with open('foo.pik', 'rb') as f:
...   x = pickle.load(f)
...   y = pickle.load(f)
... 
>>> x
[1, 2, 3, 4, 5]
>>> y
<built-in function sin>
_

また、cPickleを探している場合は、pickleではなく__pickle_になります。

_>>> import _pickle
>>> _pickle
<module '_pickle' from '/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/lib-dynload/_pickle.cpython-35m-darwin.so'>
>>> 
_

また、pickleが組み込み(C++)バージョンを使用しないようにする方法についても質問しました。これを行うには、__dump_と__load_を使用するか、クラスオブジェクトを操作する場合は__Pickler_クラスを使用します。混乱していますか?古いcPickleは現在__pickle_ですが、dumploaddumps、およびloadsはすべて__pickle_…一方、__dump_、__load_、__dumps_、および__loads_は、純粋なpythonバージョンを指します。例:

_>>> import pickle
>>> # _dumps is a python function
>>> pickle._dumps
<function _dumps at 0x109c836a8>
>>> # dumps is a built-in (C++)
>>> pickle.dumps
<built-in function dumps>
>>> # the Pickler points to _pickle (C++)
>>> pickle.Pickler 
<class '_pickle.Pickler'>
>>> # the _Pickler points to pickle (pure python)
>>> pickle._Pickler
<class 'pickle._Pickler'>
>>> 
_

したがって、組み込みバージョンを使用したくない場合は、_pickle._loads_などを使用できます。

7
Mike McKerns

Anaconda Python3.5の場合:cPickleに次のようにアクセスできます

import _pickle as cPickle

クレジット Mike McKerns

3
Shravan Kumar

これは技術的な問題を回避しますが、mnist_py3k.pkl.gzという名前のそのファイルのpy3バージョンがある可能性があります。その場合は、代わりにそのファイルを開いてみてください。

0
diggyg