Cuando intenta encurtir un objeto, puede haber algunas propiedades que no se serializan bien. Un ejemplo de esto es un mango de archivo abierto. Pickle no sabrá cómo manejar el objeto y lanzará un error.
Puede decirle al módulo Pickle cómo manejar este tipo de objetos de forma nativa dentro de una clase directamente. Veamos un ejemplo de un objeto que tiene una sola propiedad; Un mango de archivo abierto:
import pickle
class Test(object):
def __init__(self, file_path="test1234567890.txt"):
# An open file in write mode
self.some_file_i_have_opened = open(file_path, 'wb')
my_test = Test()
# Now, watch what happens when we try to pickle this object:
pickle.dumps(my_test)
Debería fallar y dar un rastreo:
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
Sin embargo, si hubiéramos definido un __reduce__
método en nuestro Test
clase, Pickle habría sabido cómo serializar este objeto:
import pickle
class Test(object):
def __init__(self, file_path="test1234567890.txt"):
# Used later in __reduce__
self._file_name_we_opened = file_path
# An open file in write mode
self.some_file_i_have_opened = open(self._file_name_we_opened, 'wb')
def __reduce__(self):
# we return a tuple of class_name to call,
# and optional parameters to pass when re-creating
return (self.__class__, (self._file_name_we_opened, ))
my_test = Test()
saved_object = pickle.dumps(my_test)
# Just print the representation of the string of the object,
# because it contains newlines.
print(repr(saved_object))
Esto debería darte algo como: "c__main__\nTest\np0\n(S'test1234567890.txt'\np1\ntp2\nRp3\n."
, que se puede usar para recrear el objeto con manijas de archivo abiertos:
print(vars(pickle.loads(saved_object)))
En general, el __reduce__
El método debe devolver una tupla con al menos dos elementos:
- Una clase de objeto en blanco para llamar. En este caso,
self.__class__
- Una tupla de argumentos para pasar al constructor de clase. En el ejemplo, es una sola cadena, que es la ruta al archivo para abrir.
Consultar el documentos Para una explicación detallada de qué más el __reduce__
El método puede devolver.