1. ホーム
  2. python

モジュールのディレクトリを変更した後の Python の pickling

2023-10-21 04:53:48

質問

私は最近、私のプログラムのディレクトリのレイアウトを変更しました:以前は、私はすべての私のモジュールを "main" フォルダの中に持っていました。以前は、すべてのモジュールを "main" フォルダ内に置いていましたが、現在は、プログラム名と同じ名前のディレクトリに移動し、その中に __init__.py を置き、パッケージを作成しました。

これで、私のメインディレクトリに、私のプログラムを起動するために使用される単一の.pyファイルができ、よりすっきりしました。

とにかく、私のプログラムの以前のバージョンからpickleされたファイルをロードしようとすると、失敗します。というメッセージが表示されます。これは、私のモジュールが以前はメイン フォルダにあり、現在は、単純な tools ではなく、whyteboard.tools にあるためだと思います。しかし、toolsモジュールでインポートしているコードは、それと同じディレクトリに住んでいるので、パッケージを指定する必要があるかどうかは疑問です。

というわけで、私のプログラムディレクトリはこんな感じです。

whyteboard-0.39.4

-->whyteboard.py

-->README.txt

-->CHANGELOG.txt

---->whyteboard/

---->whyteboard/__init__.py

---->whyteboard/gui.py

---->whyteboard/tools.py

whyteboard.py は whyteboard/gui.py からコードのブロックを起動し、GUI を起動します。このpicklingの問題は、ディレクトリの再整理を行う前には間違いなく起こっていませんでした。

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

として pickleのドキュメント にあるように、クラスインスタンス(実際には関数も)を保存・復元するためには、ある種の制約を守らなければなりません。

pickleはクラスのインスタンスを透過的に保存・復元することができます。 のインスタンスを透過的に保存・復元することができますが クラスの定義はインポート可能でなければなりません。 と同じモジュールに住んでいる必要があります。 オブジェクトが保存されたときと同じモジュールに存在しなければなりません。

whyteboard.tools ではない と同じモジュールです。 tools と同じモジュールではありません (たとえ import tools でインポートされても、結局は sys.modules として sys.modules['whyteboard.tools'] そうでなければ、同じパッケージ内の1つと別のパッケージ内の1つによってインポートされた同じモジュールは、複数の、そしておそらく衝突するエントリで終わるでしょう!) これは絶対に重要です。

もしあなたのpickleファイルが良い/高度なフォーマット(互換性の理由だけでデフォルトになっている古いアスキーフォーマットとは対照的)であれば、一度そのような変更を行った後にそれらを移行することは、実際、以下のようになるかもしれません。 ではありません。 は、他の回答が示唆しているにもかかわらず、ファイル"編集(これはバイナリ&c...!)のように非常に些細なものです。 私は、その代わりに、小さな "pickle-migrating script" を作成することを提案します。 sys.modules このように...:

import sys
from whyteboard import tools

sys.modules['tools'] = tools

で、次に cPickle.load という各ファイルがあります。 del sys.modules['tools'] であり、かつ cPickle.dump にある一時的な余分なエントリは、ファイルに戻されます。 sys.modules の一時的な余分なエントリは、ピクルスを正常にロードさせ、その後、それらを再びダンプすることは、インスタンスのクラスのための正しいモジュール名を使用しなければなりません(余分なエントリを削除すると、それが確認されるはずです)。