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

Nikolaus Rath Nikolaus at rath.org
Sat Jun 14 05:04:23 CEST 2014


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.


Best,
-Nikolaus

-- 
GPG encrypted emails preferred. Key id: 0xD113FCAC3C4E599F
Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F

             »Time flies like an arrow, fruit flies like a Banana.«


More information about the Python-Dev mailing list