zvone
zvone

Reputation: 19352

Why is it only possible to `seek` from the beginning of a text file?

Python documentation says:

In text files (those opened without a b in the mode string), only seeks relative to the beginning of the file are allowed (the exception being seeking to the very file end with seek(0, 2)).

And indeed, this fails:

with open(filename, 'rt') as f:
    f.seek(2, os.SEEK_SET)
    f.seek(2, os.SEEK_CUR)

Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
io.UnsupportedOperation: can't do nonzero cur-relative seeks

The Question

I can easily replace every f.seek(offset, os.SEEK_CUR) with f.seek(f.tell() + offset, os.SEEK_SET), so, why doesn't Python do it itself?

This works:

with open(filename, 'rt') as f:
    f.seek(2, os.SEEK_SET)
    f.seek(f.tell() + 2, os.SEEK_SET)

Am I missing something? Will this fail sometimes? What should I be careful about?

I can imagine problems with seeking into the middle of a multi-byte UTF-8 sequence, but I don't see how it makes a difference whether I seek from SEEK_SET or SEEK_CUR.

Upvotes: 4

Views: 818

Answers (1)

chepner
chepner

Reputation: 531075

I suspect f.seek(f.tell() + 2, os.SEEK_SET) is only allowed because the implementation cannot distinguish this from f.seek(f.tell(), os.SEEK_SET). From the documentation for seek:

SEEK_SET or 0: seek from the start of the stream (the default); offset must either be a number returned by TextIOBase.tell(), or zero. Any other offset value produces undefined behaviour.

Since f.tell() + 2 isn't a value returned by f.tell(), that's undefined behavior, because you aren't supposed to know what the return value of f.tell() represents, and so adding 2 to it isn't meaningful.

The idea is that the only seeks allowed are to absolute positions you saved from previous calls to f.tell(), not arbitrarily calculated positions.

Upvotes: 3

Related Questions