h5py对象作为实例变量时的困惑赋值行为
我正在使用h5py来访问HDF5文件,并把h5py的文件对象存储在一个类里。但是在尝试用一个新的文件对象替换一个已经关闭的h5py文件实例时,遇到了一些奇怪的情况:
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()
输出结果:
<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>
当我尝试用新打开的h5py文件对象更新实例变量时,似乎影响了这个对象的状态,导致它被关闭了。无论h5py的实现是什么,我觉得这种行为在我理解的Python语言中是没有道理的(也就是说,赋值操作符并没有被重载)。
这个例子是在Python 2.6.5和h5py 1.3.0下运行的。如果你想试试这个例子,但手头没有HDF5文件,可以把文件访问模式从'r'改成'a'。
2 个回答
1
不确定这是否有帮助,但我在源代码中找到了一些东西(简化版):
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()))
因为没有定义 __str__
方法,所以会调用 __repr__
方法来生成输出。__repr__
方法首先会调用 register_thread()
,然后检查 self
是否存活(简单来说,就是判断它是“真”还是“假”)。
接着,Python 会在类中查找,直到找到 __nonzero__
(这个方法也会调用 register_thread()
),然后返回 self.id.__nonzero__()
,结果显然是返回了“假”。
所以,你说得对,问题不在于名字绑定(赋值),但为什么 register_thread
和/或 self.id
出现了错误,我就不知道了。
1
没错,这是h5py 1.3中的一个已知问题,当你使用HDF5 1.8.5或更新版本时就会出现这个问题。这个问题和1.8.5版本中对标识符处理方式的变化有关。你可以通过使用HDF5 1.8.4或更早的版本来解决这个问题,或者升级到h5py 2.0版本。