пространство имен на Python Pickle - PullRequest
7 голосов
/ 28 октября 2011

Я получаю сообщение об ошибке при использовании pickle с unittest.

Я написал 3 программных файла:

  1. для класса, подлежащего маринованию,
  2. длякласс, который использует класс в # 1,
  3. unittest для тестирования класса в # 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()

Сначала я запустил программу # 1, чтобы создать файл pickle.
А затем, когда я запускаю файл программы № 2 один (т.е. введите "python SomeClass.py"), он работает.
И, когда я запускаю программу # 3 в одиночку (то есть ввод "python SomeClassTest.py"), она также работает.

Однако, когда я запускаю программу # 3 как "unit-test""в eclipse + pydev возвращает сообщение об ошибке ниже.

===========================================================================
ОШИБКА: testA (SomeClassTest.SomeClassTest)
----------------------------------------------------------------------
Traceback (последний последний вызов):
$ File "/ home / tmp / pickle_problem /SomeClassTest.py ", строка 9, в тестеA
sc = SomeClass ()
$ File" /home/tmp/pickle_problem/SomeClass.py ", строка 8, в init
self.pickle = pickle.load (open ("10.pickle", 'r'))
$ File "/usr/lib/python2.7/pickle.py", строка 1378, в загрузке
returnUnpickler (файл) .load ()
$ File "/ usr / lib / python2.7 / pickle.py ", строка 858, в загрузке
dispatchkey
Файл" /usr/lib/python2.7/pickle.py ", строка 1090, в load_global
klass = self.find_class (модуль, имя)
$ File "/usr/lib/python2.7/pickle.py", строка 1126, в find_class
klass = getattr (mod, name)
$ AttributeError: объект 'module' имеетбез атрибута 'ClassToPickle'

----------------------------------------------------------------------
Выполнен 1 тест за 0,002 с

СБОЙ (ошибки =1)

А также, когда я закомментировал строку, которая импортирует класс ClassToPickle (строка 3 в программе # 3 и закомментирована как «REQUIRED_LINE»), это не работаети верните сообщение об ошибке, описанное ниже.

E
=========================================================================== *
Ошибка: testA ( main .SomeClassTest)
----------------------------------------------------------------------
Трассировка (последний последний вызов):
Файл "SomeClassTest.py»,строка 9, в тесте A
sc = SomeClass ()
Файл "/home/tmp/pickle_problem/SomeClass.py", строка 8, в init
self.pickle = pickle.load (open ("10.pickle", 'r'))
Файл "/usr/lib/python2.7/pickle.py", строка 1378, в загрузке
return Unpickler (file) .load ()
Файл "/usr/lib/python2.7/pickle.py", строка 858, в загрузке
dispatchkey
Файл "/usr/lib/python2.7/pickle.py", строка 1090, в load_global
klass = self.find_class (модуль, имя)
Файл "/usr/lib/python2.7/pickle.py", строка 1126, в find_class
klass = getattr (мод, имя)
AttributeError: у объекта 'module' нет атрибута 'ClassToPickle'

----------------------------------------------------------------------
Пробежал 1 тест в 0,001s

FAILED (error = 1)

Я думаю, проблема в пространстве имен в Python, но я не знаю, что именно произошло и что я могу сделать дляее разрешение.

Как я могу "запустить как юнит-тест (в eclipse + pydev)" # 3 программуправильно,
и запустить программу # 3 в командной строке без строки, которая импортирует ClassToPickle?
Пожалуйста, помогите мне.

1 Ответ

9 голосов
/ 28 октября 2011

Это потому, что __main__.ClassToPickle != ClassToPickle.ClassToPickle, думайте об этом так:

Когда вы выбираете экземпляр класса ClassToPickle в сценарии ClassToPickle.py, модуль pickle будет выбирать все ссылки на класс, которые означают еговыберет имя модуля, в котором был определен класс, и поскольку вы выполнили сценарий ClassToPickle.py, это будет означать, что для модуля будет установлено значение __main__, что означает, что pickle модуль будет выбирать __main__.ClassToPickle.

И когда вы попытались загрузить маринованный экземпляр, он потерпел неудачу, потому что не нашел класс экземпляра __main__.ClassToPickle, а не тот, который вы импортировали, используя from ClassToPickle import ClassToPickle, потому что последний * ClassToPickle.ClassToPickle.

Исправление будет заключаться в создании другого скрипта, который будет обрабатывать дамп вместо того, чтобы делать это в ClassToPickle.py например,

import pickle

from ClassToPickle import ClassToPickle

if __name__=="__main__":
    p = ClassToPickle(10)
    pickle.dump(p, open('10.pickle', 'w'))
...