[Python-Dev] Why does IOBase.__del__ call .close?

Benjamin Peterson benjamin at python.org
Sat Jun 14 05:26:02 CEST 2014


On Fri, Jun 13, 2014, at 20:04, Nikolaus Rath wrote:
> Benjamin Peterson <benjamin at python.org> writes:
> > On Thu, Jun 12, 2014, at 18:06, Nikolaus Rath wrote:
> >> Consider this simple example:
> >> 
> >> $ cat test.py 
> >> import io
> >> import warnings
> >> 
> >> class StridedStream(io.IOBase):
> >>     def __init__(self, name, stride=2):
> >>         super().__init__()
> >>         self.fh = open(name, 'rb')
> >>         self.stride = stride
> >> 
> >>     def read(self, len_):
> >>         return self.fh.read(self.stride*len_)[::self.stride]
> >> 
> >>     def close(self):
> >>         self.fh.close()
> >> 
> >> class FixedStridedStream(StridedStream):
> >>     def __del__(self):
> >>         # Prevent IOBase.__del__ frombeing called.
> >>         pass
> >> 
> >> warnings.resetwarnings()
> >> warnings.simplefilter('error')
> >> 
> >> print('Creating & loosing StridedStream..')
> >> r = StridedStream('/dev/zero')
> >> del r
> >> 
> >> print('Creating & loosing FixedStridedStream..')
> >> r = FixedStridedStream('/dev/zero')
> >> del r
> >> 
> >> $ python3 test.py 
> >> Creating & loosing StridedStream..
> >> Creating & loosing FixedStridedStream..
> >> Exception ignored in: <_io.FileIO name='/dev/zero' mode='rb'>
> >> ResourceWarning: unclosed file <_io.BufferedReader name='/dev/zero'>
> >> 
> >> In the first case, the destructor inherited from IOBase actually
> >> prevents the ResourceWarning from being emitted.
> >
> > Ah, I see. I don't see any good ways to fix it, though, besides setting
> > some flag if close() is called from __del__.
> 
> How about not having IOBase.__del__ call self.close()? Any resources
> acquired by the derived class would still clean up after themselves when
> they are garbage collected.

Well, yes, but that's probably a backwards compat problem.


More information about the Python-Dev mailing list