Does Python support a peek like method for its file objects?

A

Avi Kak

Hello:

Does Python support a peek like method for its file objects?

I'd like to be able to look at the next byte in a disk file before
deciding whether I should read it with, say, the read() method.
Is it possible to do so in Python?

Your answer would be much appreciated.

Thanks.

Avi Kak
 
S

Steven D'Aprano

Hello:

Does Python support a peek like method for its file objects?

I'd like to be able to look at the next byte in a disk file before
deciding whether I should read it with, say, the read() method.
Is it possible to do so in Python?


# WARNING: untested

fp = file("some file on disk", "rb")
b = ""
while 1:
# peek at the next byte
c = fp.read(1)
# decide whether to read it
if c == "?":
# pretend we never read the byte
del c
fp.seek(-1, 1) # but be careful in text mode!
break
# now read the byte "for real"
b = fp.read(1)
if not b:
# we've reached the end of the file
break
fp.close()

I'm not sure exactly why you'd want to do this, but it should be doable,
at least for files that support seeking.
 
S

Steven D'Aprano

# WARNING: untested

Yes, and also completely broken. I don't know what I was thinking. Sigh.
Try this (also untested, but not so obviously broken):



fp = file("some file on disk", "r") # should work in text mode
b = ""
while 1:
# peek at the next byte
c = fp.read(1)
# decide whether to read it
if c == "?":
# pretend we never read the byte
fp.seek(-1, 1) # but be careful in text mode!
break
# now read the byte "for real"
b = c
if not b:
# we've reached the end of the file
break
fp.close()
 
B

Blair P. Houghton

Avi said:
Hello:

Does Python support a peek like method for its file objects?

I'd like to be able to look at the next byte in a disk file before
deciding whether I should read it with, say, the read() method.
Is it possible to do so in Python?

Your answer would be much appreciated.

If it's a seekable file (not a stream input) then you can use
file.tell() to get the current position, then file.read() to read
some data, then file.seek(), giving it the position you got from
file.tell(), to rewind to the same position. This is the safe version;
in the unsafe version you can skip the file.tell() stuff and just use
relative positioning in the file.seek() operation.

If it's a socket, you can use recv() or recvfrom() if you
set the flags argument to MSG_PEEK.

If it's a stream, you're out of luck, and you'll have to buffer the
data
yourself, although you can use select() or poll() to check on
availability of data if that's what you really want.

At least, in theory. I haven't tried any of this in Python yet.

--Blair
 
B

Blair P. Houghton

Here's a version that should work in text mode as well:

fp = file("some file on disk", "r")
b = ""
while 1:
p = fp.tell()
# peek at the next byte; moves file position only if a byte is read
c = fp.read(1)
# decide whether to read it
if c == "?":
# pretend we never read the byte
fp.seek(p)
break
# now read the byte "for real"
b = c
if not b:
# we've reached the end of the file
break
fp.close()

--Blair
 
S

Scott David Daniels

Avi said:
Does Python support a peek like method for its file objects?

A short answer is, "No, it does not." Peek was (I believe) put into
Pascal to simplify certain problems; language processing , for example,
is drastically simplified by 1-character look-ahead. Pascal was
designed as a teaching language, and it provided primitives to ease
the work students did, rather than reflect the realities of an
underlying I/O system. Building usable Pascal runtimes was a pain in
the posterior for precisely this reason.

Often you can build simple code to accomplish your task without
implementing a full peek. Peek affects: read, tell, relative seeks,
end-of-file processing, and waits for user interaction. usually you
need nearly none of this. Maybe all you need is a layer around a
reader with a "pushback" function.

class ReaderWithPushback(object):
def __init__(self, somefile):
self._read = somefile.read
self.held = ''
self.sawEOF = False

def read(self, length):
assert length > 0
while len(self.held) < length and not self.sawEOF:
chunk = self._read(length - len(self.held))
if chunk:
self.held += chunk
else:
self.sawEOF = True
if len(self.held) > length:
self.held, result = (self.held[length :],
self.held[: length])
else:
self.held, result = '', self.held
return result

def pushback(self, somestuff):
self.held = somestuff + self.held

def peek(self, length=1):
data = self.read(length)
self.pushback(data)
return data

--Scott David Daniels
(e-mail address removed)
 
D

Dennis Lee Bieber

A short answer is, "No, it does not." Peek was (I believe) put into
Pascal to simplify certain problems; language processing , for example,

At the cost of requiring some nasty special case handling of console
I/O...

Pascal, in effect, did a pre-read into a buffer. This was okay on
disk files, but how does a pre-read work on a console when there is no
available data.

A Pascal read operation moved the data from the pre-read buffer to
the user variable, and then did another pre-read for the next data item.
--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top