Я посмотрю, смогу ли я взять удар, объясняя это.
Всякий раз, когда вы пытаетесь рассолить объект, будут некоторые свойства, которые могут не сериализоваться хорошо. Например, дескриптор открытого файла. В этом случае рассол не будет знать, как обращаться с объектом, и выдает ошибку.
Вы можете сообщить модулю рассола, как обращаться с этими типами объектов изнутри непосредственно внутри класса. Давайте построим пример объекта, который имеет одно свойство; открытый дескриптор файла:
import pickle
class test(object):
def __init__(self, file_path = 'test1234567890.txt'):
self.some_file_i_have_opened = open(file_path, 'wb') # An open file in write mode.
my_test = test()
# Now, watch what happens when we try to pickle this object:
pickle.dumps(my_test)
Он должен потерпеть неудачу, и дать отслеживающий:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
--- snip snip a lot of lines ---
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy_reg.py", line 70, in _reduce_ex
raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle file objects
Однако, если бы мы определили метод __reduce__
в нашем test
class
, рассол знал бы, как сериализовать этот объект :
import pickle
class test(object):
def __init__(self, file_path = 'test1234567890.txt'):
self._file_name_we_opened = file_path # Used later in __reduce__
self.some_file_i_have_opened = open(self._file_name_we_opened, 'wb') # An open file in write mode.
def __reduce__(self):
return (self.__class__, (self._file_name_we_opened,)) # we return a tuple of class_name to call, and optional parameters to pass when re-creating
my_test = test()
saved_object = pickle.dumps(my_test)
print repr(saved_object) # Just print the representation of the string of the object, because it contains newlines.
Это должно дать вам что-то вроде: "c__main__\ntest\np0\n(S'test1234567890.txt'\np1\ntp2\nRp3\n."
, который может быть использован для воссоздания объекта с ОПОМ п дескрипторов файлов:
print vars(pickle.loads(saved_object))
Как правило, большая путаница с какой тип объекта __reduce__
должен вернуться. в то время как вы можете прочитать немного больше о том, какой тип объекта уменьшить должен вернуться в Документах страниц: http://aakashlabs.org/docs/apl/pyhelp/pydocs/library/pickle.html#pickling-and-unpickling-extension-types, но в целом, нуждается в кортеж, по крайней мере, 2 вещи:
- пустой класс объекта для вызова , В этом случае
self.__class__
- Корень аргументов для перехода к конструктору класса. В этом случае это единственная строка, которая представляет собой путь к открываемому файлу.
Есть и другие необязательные элементы, но вы должны прочитать все о них в документах.
Надеюсь, что это поможет!
Но то же самое может быть достигнуто с помощью '__get_state__',' __set_state__'. – Sklavit
@ Склавит, который лучше использовать? '__get_state__' /' __set_state__' или '__reduce__'? –
@JasonS Как я понимаю '__get_state_' /' __set_state__' - это интерфейс высокого уровня, '__reduce__' - низкий уровень. Поэтому я предпочитаю использовать интерфейс высокого уровня. – Sklavit