Comportamiento de asignación desconcertante con objeto H5PY como variable de instancia
Pregunta
Estoy usando H5PY para acceder a los archivos HDF5 y almacenar los objetos del archivo H5PY en una clase. Pero estoy experimentando un comportamiento extraño al intentar reasignar una variable de instancia de archivo H5PY cerrada con una nueva:
class MyClass:
def __init__(self, filename):
self.h5file = None
self.filename = filename
def vartest(self):
self.h5file = h5py.File(self.filename, 'r')
print self.h5file
self.h5file.close()
print self.h5file
newh5file = h5py.File(self.filename, 'r')
print newh5file
self.h5file = newh5file
print self.h5file
print newh5file
def main():
filename = sys.argv[1]
mycls = MyClass(filename)
mycls.vartest()
Producción:
<HDF5 file "test.h5" (mode r, 92.7M)>
<Closed HDF5 file>
<HDF5 file "test.h5" (mode r, 92.7M)>
<Closed HDF5 file>
<Closed HDF5 file>
Intentar actualizar la variable de instancia con el objeto de archivo H5PY recién abierto parece haber afectado de alguna manera el estado del objeto, cerrándola. Independientemente de la implementación en el lado H5PY, no veo cómo este comportamiento tiene sentido a mi comprensión del lenguaje de Python (es decir, sin sobrecarga del operador de tarea).
Este ejemplo se ejecuta con Python 2.6.5 y H5Py 1.3.0. Si desea probar este ejemplo, pero no tiene un archivo HDF5 sentado, puede cambiar el modo de acceso al archivo de 'R' a 'A'.
Solución
Sí, este es un error conocido en H5PY 1.3, que aparece cuando usa HDF5 1.8.5 o más nuevo. Está relacionado con los cambios en la forma en que se manejan los identificadores en 1.8.5. Puede solucionarlo usando HDF5 1.8.4 o anterior, o actualizando a H5PY 2.0.
Otros consejos
No estoy seguro de si esto ayudará, pero la búsqueda a través del código fuente encontré esto (abreviado):
class HLObject(object):
def __nonzero__(self):
register_thread()
return self.id.__nonzero__()
class Group(HLObject, _DictCompat):
...
class File(Group):
def __repr__(self):
register_thread()
if not self:
return "<Closed HDF5 file>"
return '<HDF5 file "%s" (mode %s, %s)>' % \
(os.path.basename(self.filename), self.mode,
_extras.sizestring(self.fid.get_filesize()))
Porque no hay __str__
método, __repr__
está llamado a producir la salida y __repr__
Primeras llamadas register_thread()
, luego verifica para ver si self
está vivo (mejor conocido como evaluación de verdadero o falso).
Python luego busca en las clases hasta que encuentre __nonzero__
(que vuelve a llamar register_thread()
), luego regresa self.id.__nonzero__()
, que aparentemente está volviendo falso.
Entonces, tiene razón en que el problema no es con el nombre vinculante (asignación), sino por qué register_thread
y/o self.id
te está bombardeando, no lo sé.