The last 5 lines at the end will test it by printing the
nominal (sometimes untrue) length, the current length of
the internal buffer, and (via pipe to unix 'nl' ) the
line numbered lines of 'flines.py'
- Steve Majewski <sdm7g@Virginia.EDU>
#--------------
# Class Flines
#
# This is a demonstration/test of a class that "lazily" coerces
# the lines of a file into a sequence.
# It was written mostly to test the technique of lying about
# the length of the sequence by +1, except at the end.
# It has the feature that it will continue to try to read
# file when it gets to eof, so even if file continues to grow,
# so that:
# for x in flines_obj: print x[:-1]
# will always print whatever is currently available.
# So it's actually good for something.
# ( But that also means that flines_obj[-1] is very context sensitive! )
#
# <sdm7g@Virginia.EDU>
#
import posix
import builtin
def rdopen( fname ): # open file or pipe for reading
if fname[-1] == '|' :
open = posix.popen
fname = fname[:-1]
else: open = builtin.open
return open( fname, 'r' )
class Flines:
def _lie( self ): return self._len + 1
def _get1( self ):
if self._cache[-1]:
self._cache.append( self._file.readline() )
self._len = self._len + 1
else:
self._cache[-1] = self._file.readline()
def __init__( self, fname ):
self._file = rdopen( fname )
self._cache = [ self._file.readline() ]
self._len = 1
def __len__( self ):
if self._cache[-1]:
return self._lie()
else:
self._get1()
if self._cache[-1]: return self._lie()
else: return self._len
def __getitem__( self, j ):
if j < 0 :
self._get1()
elif j >= self._len :
for index in range( self._len, j+1 ): self._get1()
return self._cache[j]
def __del__(self):
self._file.close()
def __getslice__( self, i, j ):
return self._cache[i:j]
F=Flines('nl -ba flines.py|' )
print '# Test me once...'
for x in F : print len(F),F._len, x[:-1]
print '# Test me twice ... '
for x in F : print len(F),F._len, x[:-1]