python 3, subclassing TextIOWrapper.

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Sun Mar 22 17:26:58 CET 2009


En Sat, 21 Mar 2009 23:58:07 -0300, <lambertdw at corning.com> escribió:

> '''
>     A python 3 question.
>     Presume this code is in file p.py.
>     The program fails.
>
>         $ python3 p.py
>         ...
>         ValueError: I/O operation on closed file.
>
>     Removing the comment character to increase the stream
>     reference count fixes the program, at the expense of
>     an extra TextIOWrapper object.
>
>     Please, what is a better way to write the class with
>     regard to this issue?
> '''
>
> import re
> import io
>
> class file(io.TextIOWrapper):
>
>     '''
>         Enhance TextIO.  Streams have many sources,
>         a file name is insufficient.
>     '''
>
>     def __init__(self,stream):
>         #self.stream = stream
>         super().__init__(stream.buffer)
>
>
> print(file(open('p.py')).read())

You're taking a shortcut (the open() builtin) that isn't valid here.

open() creates a "raw" FileIO object, then a BufferedReader, and finally  
returns a TextIOWrapper. Each of those has a reference to the previous  
object, and delegates many calls to it. In particular, close() propagates  
down to FileIO to close the OS file descriptor.

In your example, you call open() to create a TextIOWrapper object that is  
discarded as soon as the open() call finishes - because you only hold a  
reference to the intermediate buffer. The destructor calls close(), and  
the underlying OS file descriptor is closed.

So, if you're not interested in the TextIOWrapper object, don't create it  
in the first place. That means, don't use the open() shortcut and build  
the required pieces yourself.

---

There is another alternative that relies on undocumented behaviour: use  
open to create a *binary* file and wrap the resulting BufferedReader  
object in your own TextIOWrapper.

import io

class file(io.TextIOWrapper):
      def __init__(self, buffer):
          super().__init__(buffer)

print(file(open('p.py','rb')).read())

-- 
Gabriel Genellina




More information about the Python-list mailing list