Prevent TextIOWrapper from closing on GC in a Py2/Py3 compatible way

前端 未结 4 645
面向向阳花
面向向阳花 2021-01-12 02:34

What I need to accomplish:

Given a binary file, decode it in a couple different ways providing a TextIOBase API. Ideally these subseque

4条回答
  •  被撕碎了的回忆
    2021-01-12 02:55

    EDIT:

    I found a much better solution (comparatively), but I will leave this answer in the event it is useful for anyone to learn from. (It is a pretty easy way to show off gc.garbage)

    Please do not actually use what follows.

    OLD:

    I found a potential solution, though it is horrible:

    What we can do is set up a cyclic reference in the destructor, which will hold off the GC event. We can then look at the garbage of gc to find these unreferenceable objects, break the cycle, and drop that reference.

    In [1]: import io
    
    In [2]: class MyTextIOWrapper(io.TextIOWrapper):
       ...:     def __del__(self):
       ...:         if not hasattr(self, '_cycle'):
       ...:             print "holding off GC"
       ...:             self._cycle = self
       ...:         else:
       ...:             print "getting GCed!"
       ...:
    
    In [3]: def mangle(x):
       ...:     MyTextIOWrapper(x)
       ...:     
    
    In [4]: f = io.open('example', mode='rb')
    
    In [5]: mangle(f)
    holding off GC
    
    In [6]: f.closed
    Out[6]: False
    
    In [7]: import gc
    
    In [8]: gc.garbage
    Out[8]: []
    
    In [9]: gc.collect()
    Out[9]: 34
    
    In [10]: gc.garbage
    Out[10]: [<_io.TextIOWrapper name='example' encoding='UTF-8'>]
    
    In [11]: gc.garbage[0]._cycle=False
    
    In [12]: del gc.garbage[0]
    getting GCed!
    
    In [13]: f.closed
    Out[13]: True
    

    Truthfully this is a pretty horrific workaround, but it could be transparent to the API I am delivering. Still I would prefer a way to override the __del__ of IOBase.

提交回复
热议问题