1. ホーム
  2. python

[解決済み] Python 2のオブジェクトをPython 3でアンピッキングする

2022-05-17 04:34:39

質問

Python 2.4でpickleしたオブジェクトを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)

競合するpickleオブジェクトを見ると、それは dict の中に dict 型のキーと値を含む str .

Python 2.4でpickleされたオブジェクトをpython 3.4で読み込む方法はありますか?

どのように解決するのですか?

次のことを伝えなければなりません。 pickle.load() に、Python のバイト列データを Python 3 の文字列に変換する方法、あるいは pickle でバイトのままにしておくこともできます。

デフォルトでは、すべての文字列データをASCIIとしてデコードしようとし、そのデコードは失敗します。参照 pickle.load() のドキュメントを参照してください。 :

オプションのキーワード引数は fix_imports , エンコーディング エラー これらは、Python 2で生成されるpickleストリームの互換性サポートを制御するために使用されます。もし fix_imports が真なら、pickleは古いPython 2の名前をPython 3で使われる新しい名前にマップしようとします。その際 エンコーディング エラー は、Python 2でpickleされた8ビット文字列インスタンスのデコード方法を指示します; これらはそれぞれ、'ASCII' と 'strict' がデフォルトです。また エンコーディング には 'bytes' を指定すると、これらの8ビット文字列をbytesオブジェクトとして読み込むことができます。

エンコーディングの設定に 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 オブジェクトのデータは壊れています。 を使用しない限り encoding='bytes' .