Python 2.4でPython 3.4を使用してピクルされたオブジェクトをロードする方法があるかどうか疑問に思っています。
最新の状態にするために、大量の会社のレガシーコードで2to3を実行しています。
これを行った後、ファイルを実行すると、次のエラーが表示されます。
File "H:\fixers - 3.4\addressfixer - 3.4\trunk\lib\address\address_generic.py"
, line 382, in read_ref_files
d = pickle.load(open(mshelffile, 'rb'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1: ordinal
not in range(128)
競合するピクルされたオブジェクトを見ると、それはdict
のdict
であり、str
型のキーと値を含んでいます。
だから私の質問は次のとおりです。元はpython 2.4でpython 3.4で漬けられたオブジェクトをロードする方法はありますか?
pickle.load()
にPythonバイト文字列データをPython 3文字列に変換する方法を指示するか、pickle
にバイトとして残すように指示する必要があります。
デフォルトでは、すべての文字列データをASCIIとしてデコードしようとしますが、そのデコードは失敗します。 pickle.load()
documentation を参照してください:
オプションのキーワード引数は、fix_imports、encodingおよびerrors。Pythonによって生成されたpickleストリームの互換性サポートを制御するために使用されます。2. iffix_importsがtrueの場合、pickleは古いPython 2の名前をPython 3.で使用される新しい名前にマップしようとします。encoding およびerrorsは、Python 2によってpickle化された8ビット文字列インスタンスをデコードする方法をpickleに指示します。これらのデフォルトはそれぞれ「ASCII」と「strict」です。 encodingを「バイト」にして、これらの8ビット文字列インスタンスをバイトオブジェクトとして読み取ることができます。
エンコードをlatin1
に設定すると、データを直接インポートできます。
with open(mshelffile, 'rb') as f:
d = pickle.load(f, encoding='latin1')
ただし、間違ったコーデックを使用して文字列がデコードされていないことを確認する必要があります。 Latin-1は、0〜255のバイト値を最初の256個のUnicodeコードポイントに直接マッピングするため、あらゆる入力に対して機能します。
別の方法としては、encoding='bytes'
を使用してデータをロードし、その後すべてのbytes
キーと値をデコードします。
3.6.8、3.7.2、および3.8.0より前のPythonバージョンまで、 Python 2 datetime
オブジェクトデータのunpickle化が壊れているencoding='bytes'
。
Encoding = 'latin1'を使用すると、オブジェクトにnumpy配列が含まれている場合に問題が発生します。
Encoding = bytesを使用する方が適切です。
Encoding = bytesの使用に関する完全な説明については、こちらをご覧ください answer