Trouble with file.seek/file.tell on Win32?

Tim Peters tim.peters at gmail.com
Sun Aug 15 15:49:45 EDT 2004


[Prabhu Ramachandran]
> I noticed peculiar behavior under Python-2.3.4 under Win32.  When I
> run something like this:
>
> f = open('t.txt', 'wb')
> f.write('1\012'+'2\012'+'3\012')
> f.close()
> f = open('t.txt', 'r')

Sorry, you're in trouble already.  You can *tell* Windows that's a
text file, but it doesn't contain native Windows text-file data (it
has the wrong kind of line end for Windows).

> f.readline()
> pos = f.tell()
> val = f.read(1)
> f.seek(pos)
> assert val == f.read(1)
>
> I get an assertion error at this point.  Everything works fine if I
> read the file with 'rb' instead of 'r'.

Yes, then you're not lying to Windows about the kind of data it contains.

> But I can almost swear that this used to work earlier.  I suspect that
> this behavior arises due to recent changes in fileobject.c (specifically,
> v2.187) where universal newline support was removed.

Nope.

> Could someone please clarify if this is this a bug or not?  I would
> like to think that using tell and seek should work reliably enough for
> text files.

They do, provided they really are text files.

Let's add more output to your program:

f = open('t.txt', 'wb')
if 1:
    f.write('1\012'+'2\012'+'3\012')
else:
    f.write('1\r\n'+'2\r\n'+'3\r\n')
f.close()
f = open('t.txt', 'r')
f.readline()
pos = f.tell()
print 'pos', pos
val = f.read(1)
print 'read', repr(val)
f.seek(pos)
val2 = f.read(1)
print 'read', repr(val2)

That displays this when I run it on Windows:

pos 0
read '2'
read '1'

Now here's a C program on Windows:

#include <stdio.h>
void main() {
    char buf[100];
    long pos;
    FILE *f = fopen("t.txt", "wb");
    fputs("1\n2\n3\n", f);
    fclose(f);
    f = fopen("t.txt", "r");
    fgets(buf, sizeof(buf), f);
    pos = ftell(f);
    printf("pos %ld\n", pos);
    fread(buf, 1, 1, f);
    printf("read '%c'\n", buf[0]);
    fseek(f, pos, 0);
    fread(buf, 1, 1, f);
    printf("read '%c'\n", buf[0]);
}

And here's what that displays:

pos 0
read '2'
read '1'

Same thing:  the Python program has exactly the same behavior as the C program.

If you change "if 1" to "if 0" in my rewritten version, it creates a
legitimate Windows text file instead, and then the output changes:

pos 3
read '2'
read '2'

Same thing if the C program is changed similarly.

> The reason this is important for me is that I've been generating text
> files (with gay abandon) for MayaVi (http://mayavi.sf.net) for three
> years now.  I always open the file using 'r'/'w' and not 'rb'/'wb'.
> Everything used to work fine.

I think you must be confusing something.  Your program had the same
behavior in 2.2.3 on Windows too, which is the oldest Python I have
handy.  It could have appeared to work by accident in some cases,
though.

...
> p.s. Please CC me in on replies.  I'm not tracking c.l.py.  Thanks.

OK, done.



More information about the Python-list mailing list