私は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)cPickle
もcpickle
もプロジェクト内のどのソースファイルにも表示されなくなり(グローバルに検索)、b)load_data()
Pythonシェルで個別に(ただし、別のデータ形式エラーが発生します)。pickle
はcPickle
を呼び出していますか?その場合はどうすればよいですか?やめますか?
シェル: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
続行する方法が不明です。助けていただければ幸いです。ありがとう。
ロードしようとしている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)で任意のコードを実行することと同等です)は積極的に避ける必要があります。とりわけ、あなたが自分自身を見つけた正確なケースのためです。
実際、_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
_ですが、dump
、load
、dumps
、および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
_などを使用できます。
これは技術的な問題を回避しますが、mnist_py3k.pkl.gzという名前のそのファイルのpy3バージョンがある可能性があります。その場合は、代わりにそのファイルを開いてみてください。