Why does StringIO discard its initial value?

David Fraser davidf at sjsoft.com
Tue Apr 12 05:08:35 EDT 2005


Raymond Hettinger wrote:
> [Leif K-Brooks]
> 
>>The obvious workaround is to call buffer.write() with the initial value
>>instead of passing it to StringIO's constructor,
> 
> 
> More than just a workaround, it is the preferred approach.
> That makes is easier to switch to cStringIO where initialized objects are
> read-only.
> 

Others may find this helpful ; it's a pure Python wrapper for cStringIO 
that makes it behave like StringIO in not having initialized objects 
readonly. Would it be an idea to extend cStringIO like this in the 
standard library? It shouldn't lose performance if used like a standard 
cStringIO, but it prevents frustration :-)

David

class StringIO:
     def __init__(self, buf = ''):
         if not isinstance(buf, (str, unicode)):
             buf = str(buf)
         self.len = len(buf)
         self.buf = cStringIO.StringIO()
         self.buf.write(buf)
         self.buf.seek(0)
         self.pos = 0
         self.closed = 0

     def __iter__(self):
         return self

     def next(self):
         if self.closed:
             raise StopIteration
         r = self.readline()
         if not r:
             raise StopIteration
         return r

     def close(self):
         """Free the memory buffer.
         """
         if not self.closed:
             self.closed = 1
             del self.buf, self.pos

     def isatty(self):
         if self.closed:
             raise ValueError, "I/O operation on closed file"
         return False

     def seek(self, pos, mode = 0):
         if self.closed:
             raise ValueError, "I/O operation on closed file"
         self.buf.seek(pos, mode)
         self.pos = self.buf.tell()

     def tell(self):
         if self.closed:
             raise ValueError, "I/O operation on closed file"
         return self.pos

     def read(self, n = None):
         if self.closed:
             raise ValueError, "I/O operation on closed file"
         if n == None:
           r = self.buf.read()
         else:
           r = self.buf.read(n)
         self.pos = self.buf.tell()
         return r

     def readline(self, length=None):
         if self.closed:
             raise ValueError, "I/O operation on closed file"
         if length is not None:
             r = self.buf.readline(length)
         else:
             r = self.buf.readline(length)
         self.pos = self.buf.tell()
         return r

     def readlines(self):
         if self.closed:
             raise ValueError, "I/O operation on closed file"
         lines = self.buf.readlines()
         self.pos = self.buf.tell()
         return lines

     def truncate(self, size=None):
         if self.closed:
             raise ValueError, "I/O operation on closed file"
         self.buf.truncate(size)
         self.pos = self.buf.tell()
         self.buf.seek(0, 2)
         self.len = self.buf.tell()
         self.buf.seek(self.pos)

     def write(self, s):
         if self.closed:
             raise ValueError, "I/O operation on closed file"
         origpos = self.buf.tell()
         self.buf.write(s)
         self.pos = self.buf.tell()
         if origpos + len(s) > self.len:
           self.buf.seek(0, 2)
           self.len = self.buf.tell()
           self.buf.seek(self.pos)

     def writelines(self, lines):
         if self.closed:
             raise ValueError, "I/O operation on closed file"
         self.buf.writelines(lines)
         self.pos = self.buf.tell()
         self.buf.seek(0, 2)
         self.len = self.buf.tell()
         self.buf.seek(self.pos)

     def flush(self):
         if self.closed:
             raise ValueError, "I/O operation on closed file"
         self.buf.flush()

     def getvalue(self):
         if self.closed:
             raise ValueError, "I/O operation on closed file"
         return self.buf.getvalue()



More information about the Python-list mailing list