2011-09-08 5 views
3

h5py를 사용하여 HDF5 파일에 액세스하고 h5py File 개체를 클래스에 저장합니다. 그러나 나는 새와 폐쇄 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와 인스턴스 변수를 갱신하려고 File 객체는 어떻게 든 객체의 상태에 영향을 미쳐 닫힌 것처럼 보입니다. h5py 측의 구현에 관계없이이 동작이 파이썬 언어에 대한 내 이해 (즉, 대입 연산자의 오버로드 없음)에서 어떻게 이해되는지는 알 수 없습니다.

이 예제는 Python 2.6.5 및 h5py 1.3.0으로 실행됩니다. 이 예제를 시도하고 싶지만 주변에 HDF5 파일이 없으면 파일 액세스 모드를 'r'에서 'a'로 변경할 수 있습니다.

+0

'self.h5file = newh5file' 행을 주석 처리하면 "닫힘"으로 인쇄됩니까? 'self.h5file'은 [property] (http://docs.python.org/library/functions.html#property)입니까? 'h5py.File()'은 전역 상태를 유지합니까? – jfs

+0

만약'self.h5file = newh5file'을 주석 처리했다면 흥미롭게도'newh5file'과'self.h5file' (내가 명시 적으로 닫은 것)은''. 이 예제는 독립적인데, self.h5file은 속성이 아닙니다. 'h5py.File()'의 구현에 관해서는 많이 말할 수 없지만, 어떤 전역 상태가 있다면 놀라지 않을 것입니다. 그러나 인스턴스 변수를 할당하는 것이 어떻게 전역 상태를 변경하는지 이해하지 못합니다 (누군가 참조 계산을 어딘가에서하고 있습니까?). –

답변

1

예, 이것은 h5py 1.3의 알려진 버그이며, HDF5 1.8.5 이상을 사용하는 경우 나타납니다. 식별자가 1.8.5에서 처리되는 방식의 변화와 관련이 있습니다. HDF5 1.8.4 이전 버전을 사용하거나 h5py 2.0으로 업그레이드하여 문제를 해결할 수 있습니다.

+0

고마워, 나는 그것을 시험해 볼 것이다. 당신이 우연히 메일 링리스트 게시물이나 이것을 설명하는 버그 보고서에 대한 참조를 가지고 있다면 도움이 될 것이다. –

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())) 

__repr__ 첫번째 호출이, __repr__는 출력을 생성하기 위해 호출됩니다 더 __str__ 방법은 없으며, 때문에 register_thread()을 입력 한 다음 self이 살아 있는지 확인합니다 (true 또는 false로 평가 됨).

그러면 파이썬은 __nonzero__ (다시 register_thread())을 찾을 때까지 클래스를 검색 한 다음 self.id.__nonzero__()을 반환합니다. 그러면 분명히 False가 반환됩니다.

그래서 문제는 이름 바인딩 (할당)이 아니라는 점에서 옳은 점이 있지만 register_thread 및/또는 self.id이 왜 나올지 모르겠다.

+0

재미 있습니다. 나는 __nonzero__에 익숙하지 않았다. 설명에 감사한다. –

+0

@David 문제가 없습니다. 파이썬 3에서'__nonzero__'는'__bool__'으로 이름이 변경되었습니다; 또한이 메소드가 존재하지 않으면'__len__'이 시도됩니다 (0 ='거짓', 그렇지 않으면'참'). '__len__'도 존재하지 않으면, 그 클래스의 모든 인스턴스는'True'로 간주됩니다. –