Pythonのピクルスの名前空間

私はunittestでpickleを使うとエラーになります。

私は3つのプログラムファイルを書いた:

  1. クラスを節約するには、
  2. #1でクラスを使用するクラスの場合
  3. #2でクラスをテストするためのユニットテスト。

実コードはそれぞれ以下の通りである。

#1。 ClassToPickle.py

import pickle
class ClassToPickle(object):
    def __init__(self, x):
        self.x = x
if __name__=="__main__":
    p = ClassToPickle(10)
    pickle.dump(p, open('10.pickle', 'w'))

#2。 SomeClass.py

from ClassToPickle import ClassToPickle
import pickle

class SomeClass(object):
    def __init__(self):
        self.pickle = pickle.load(open("10.pickle", 'r'))
        self.x = self.pickle.x
        print self.x

if __name__ == "__main__":
    SomeClass()

#3。 SomeClassTest.py

import unittest
from SomeClass import SomeClass
from ClassToPickle import ClassToPickle # REQUIRED_LINE

class SomeClassTest(unittest.TestCase):
    def testA(self):
        sc = SomeClass()
        self.assertEqual(sc.x, 10)

def main():
    unittest.main()

if __name__ == "__main__":
    main()

I ran #1 program first to make pickle file.
And then, when I run program file #2 alone (i.e. enter "python SomeClass.py"), it works.
And, when I run program #3 alone (i.e. enter "python SomeClassTest.py"), it also works.

しかし、eclipse + pydevでプログラム#3を "unit-test"として実行すると、以下のエラーメッセージが返されます。

=========================================== =======================================================   エラー:testA(SomeClassTest.SomeClassTest)
  -------------------------------------------------- --------------------
  トレースバック(直近の最後のコール):
$ File   "/home/tmp/pickle_problem/SomeClassTest.py"、9行目、   testA
      sc = SomeClass()
$ファイル "/home/tmp/pickle_problem/SomeClass.py"、8行目   初期化
      self.pickle = pickle.load(open( "10.pickle"、 'r'))
$ file "/usr/lib/python2.7/pickle.py"、行1378、ロード中
      return Unpickler(file).load()
$ file "/usr/lib/python2.7/pickle.py"、行858、ロード中
      ディスパッチキー
ファイル "/usr/lib/python2.7/pickle.py"、1090行目、load_global
      klass = self.find_class(モジュール、名前)
find_classの$ file "/usr/lib/python2.7/pickle.py"、1126行目
      klass = getattr(mod、name)
$ AttributeError: 'module'オブジェクトに 'ClassToPickle'属性がありません

  -------------------------------------------------- -------------------- 0.002秒でRan 1テスト

FAILED(errors = 1)
  

また、ClassToPickleクラス(プログラム#3の3行目と "REQUIRED_LINE"とコメントした行)をインポートする行をコメントアウトしたときに、それは機能せず、以下で説明するエラーメッセージを返します。

E
  ========================================== ====================   エラー:testA(メイン .SomeClassTest)
  -------------------------------------------------- --------------------
  トレースバック(最近の最後のコール):
    ファイル "SomeClassTest.py"、9行目、testA
      sc = SomeClass()
     init の "/home/tmp/pickle_problem/SomeClass.py"ファイルの8行目
      self.pickle = pickle.load(open( "10.pickle"、 "r"))
    ファイル "/usr/lib/python2.7/pickle.py"、行1378、ロード中
      Unpickler(file).load()
    ファイル "/usr/lib/python2.7/pickle.py"、行858、ロード中
      ディスパッチキー
    ファイル "/usr/lib/python2.7/pickle.py"、行1090、load_global
      klass = self.find_class(モジュール、名前)
    find_class
"/usr/lib/python2.7/pickle.py"、1126行目のファイル       klass = getattr(mod、name)
  AttributeError: 'module'オブジェクトに 'ClassToPickle'属性がありません
  
  -------------------------------------------------- --------------------
  0.001秒でラン1テスト   
  FAILED(エラー= 1)

私は、問題はPythonの名前空間に関するものだと思うが、私は何が起こったのか、それを解決するために何ができるのか分からない。

どうすれば "ユニットテスト(eclipse + pydevで)"#3プログラムを正しく実行できますか? ClassToPickleをインポートする行がないコマンドラインで#3プログラムを実行しますか?
私を助けてください。

5
@ThomasKあなたのコメントをありがとうございますが、答えはいいえです。ここに示した3つの.pyファイルのみがディレクトリにあり、 ClassToPickle.py という名前のファイルを作成したことはありません。
追加された 著者 fbessho,
他の ClassToPickle.py ファイルは、あなたがここに示したファイルの代わりに見つけることができる場所ですか?
追加された 著者 Thomas K,

1 答え

これは、 __ main __。ClassToPickle!= ClassToPickle.ClassToPickle のように、次のように考える:

ClassToPickle.py スクリプトでClassToPickleのクラスインスタンスをpickleしたとき、pickleモジュールはクラスへの参照をすべてピクルします。つまり、クラスが定義されたモジュール名をpickleします。 pickle モジュールが __ main __をpickleすることを意味する __ main __ にモジュールが設定されることを意味する ClassToPickle.py

そして、pickle化されたインスタンスをロードしようとすると、 __ main __。ClassToPickle であり、ClassToPickleからを使用してインポートしたクラスではなく、インスタンスのクラスが見つからなかったため失敗します。ClassToPickle これは最新の ClassToPickle.ClassToPickle です。

解決策は、 ClassToPickle.py でダンプする代わりに、ダンプを処理する別のスクリプトを作成することです。

import pickle

from ClassToPickle import ClassToPickle

if __name__=="__main__":
    p = ClassToPickle(10)
    pickle.dump(p, open('10.pickle', 'w'))
7
追加された
@fbessho:嬉しかったです:)
追加された 著者 mouad,
あなたの説明をありがとう!それはすべて私には意味があり、あなたのスクリプトはコンソールとEclipseの両方で動作します:)
追加された 著者 fbessho,