python - ran - ¿Por qué pickle protocol 2 me permite serializar un objeto de archivo abierto?
pickle.loads example (2)
Considerar:
>>> import pickle
>>> thing = open(''foobar.txt'',''w'')
>>> pickle.dumps(thing)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/pickle.py", line 1366, in dumps
Pickler(file, protocol).dump(obj)
File "/usr/lib/python2.6/pickle.py", line 224, in dump
self.save(obj)
File "/usr/lib/python2.6/pickle.py", line 306, in save
rv = reduce(self.proto)
File "/usr/lib/python2.6/copy_reg.py", line 70, in _reduce_ex
raise TypeError, "can''t pickle %s objects" % base.__name__
TypeError: can''t pickle file objects
Parece del todo razonable, por supuesto que no puedo descifrar un identificador de archivo abierto. Pero:
>>> pickle.dumps(thing, 2)
''/x80/x02c__builtin__/nfile/nq/x00)/x81q/x01.''
>>> pickle.loads(pickle.dumps(thing, 2))
<closed file ''<uninitialized file>'', mode ''<uninitialized file>'' at 0x7ff3c078>
Aparentemente puedo decapado un archivo abierto, pero no útil.
¿Es esto deliberado? Estaba ocultando un error en mi código, donde estaba decapando erróneamente un objeto que poseía un archivo. Bajo ciertas condiciones, ese objeto también tiene un cursor pyodbc
, con el mismo resultado.
No veo nada en PEP 307 al respecto. ¿Fue solo un descuido, o hay algo importante en juego que me estoy perdiendo, que podría permitirme obtener la excepción que quiero, incluso cuando utilizo el protocolo 2?
Estoy usando Python 2.6.5. Lo sé, lo sé, pero es lo que viene con mi distribución.
En la Wiki de Python , dice
No puede decapar objetos de archivos abiertos, conexiones de red o conexiones de base de datos. Cuando piensas en ello, tiene sentido: pickle no puede permitir que exista la conexión para el objeto de archivo cuando se deshaga de tu objeto, y el proceso de crear esa conexión va más allá de lo que pickle puede hacer automáticamente por ti. Si realmente quiere decantar algo que tiene un atributo que está causando problemas, consulte la documentación de pickle para
__getstate__
,__setstate__
y__getinitargs__
: con estos puede excluir los atributos problemáticos.
Sin embargo, encontré este informe de error que indica que en realidad puedes declinar objetos de archivo. Esto parece ser involuntario. Se ha corregido en Python 3.2.
Puedes ver si puedes adaptar ese parche a Python 2.6 si quisieras evitar que suceda. De lo contrario, solo tienes que tener cuidado con lo que encurtes.
Si está buscando un mejor comportamiento, puede usar dill
... que no serializará objetos similares a los archivos, pero que sabe cómo serializar los manejadores de archivos. El comportamiento es que si el archivo existe, dill
apuntará el identificador de archivo deserializado hacia él ... y si el archivo no existe, entonces el identificador de archivo se cerrará.
Python 2.7.8 (default, Jul 3 2014, 05:59:29)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>>
>>> thing = open(''foobar.txt'', ''w'')
>>> thing
<open file ''foobar.txt'', mode ''w'' at 0x10e3c2c00>
>>> dill.loads(dill.dumps(thing))
<open file ''foobar.txt'', mode ''w'' at 0x10e3c2c90>
>>>
Obtenga dill
aquí: https://github.com/uqfoundation