stdin - seek() issue on Linux.

jepler at unpythonic.net jepler at unpythonic.net
Tue Apr 23 22:50:48 EDT 2002


On Tue, Apr 23, 2002 at 07:16:41PM -0700, Srihari Vijayaraghavan wrote:
> Once again thanks for your responses. I really appreciate that.
> 
> OK. IMHO sys.stdin doesn't work as stated in PLR (Python Library
> Reference), i.e., it doesn't work like a _real_ file object,
> particularly not supporting seek() related operations. While your
> technical explanation sounds OK to me, but I am still not convinced
> why PLR advertises that sys.stdin is treated as a file object. Please
> correct me if I am wrong here (as I am still a newbie user :-).

Please try the following C program with STDIN both as a terminal and as a
file:
    cat > test_seek.c <<EOF
    #include <stdio.h>     /* perror() */
    #include <sys/types.h> /* lseek() */
    #include <unistd.h>    /* lseek() */
    #include <errno.h>     /* errno */
    int main(void) {
	errno = 0;
	lseek(0, 0, SEEK_SET);
	perror("lseek");
	return 0;
    }
    EOF
    cc test_seek.c -o test_seek
    ./test_seek  # fails 'lseek: Illegal seek'
    ./test_seek < /dev/null  # succeeds 'lseek: Success'
    
or this Perl program:
    perl -e 'seek STDIN, 0, 0 or die $!' # fails: Illegal seek at -e line 1.'
    perl -e 'seek STDIN, 0, 0 or die $!' < /dev/null # sicceeds

Not all files are seekable.  On Unix, notable exceptions are terminals,
pipes, and sockets.

If you don't know in advance whether a particular "file" is seekable, you
can test it without any side-effects by
    try:
	f.seek(0, 1)
    except IOError:
	f is not seekable (wrap with CStringIO or temporary file if
	    seeking is required)
    else:
	f is seekable
f.seek(0, 1) seeks 0 bytes from the current position.  This should succeed
without changing anything on a normal file, and fail without changing
anything on a non-seekable file.

A note to people coming from a DOS background: In DOS, a pipeline "a|b"
writes the output from a to a temporary file, then invokes b with its input
from that temporary file.  In Unix, a pipeline "a|b" executes a and b at
the same time with a "pipe" connecting the two processes.  This difference
can be noticed when trying to seek, and sometimes when there are buffering
effects in the pipe between A and B.

One last note -- the file descriptor returned by popen*() is also
non-seekable.

Jeff





More information about the Python-list mailing list