Seeking from end of file throwing unsupported exception
The existing answers do answer the question, but provide no solution.
As pointed out in the comments, this answer is based on undefined behavior and does not handle UnicodeDecodeError, which you may encounter with UTF-8 files. It works fine with ASCII and other fixed-width encodings as long as you seek to the beginning of a character. Please see Philip's answer which includes a workaround and further comments discussing why seeking backwards in UTF-8 is a problem.
From readthedocs:
If the file is opened in text mode (without
b
), only offsets returned bytell()
are legal. Use of other offsets causes undefined behavior.
This is supported by the documentation, which says that:
In text files (those opened without a
b
in the mode string), only seeks relative to the beginning of the file [os.SEEK_SET
] are allowed...
This means if you have this code from old Python:
f.seek(-1, 1) # seek -1 from current position
it would look like this in Python 3:
f.seek(f.tell() - 1, os.SEEK_SET) # os.SEEK_SET == 0
Solution
Putting this information together we can achieve the goal of the OP:f.seek(0, os.SEEK_END) # seek to end of file; f.seek(0, 2) is legal
f.seek(f.tell() - 3, os.SEEK_SET) # go backwards 3 bytes
From the documentation for Python 3.2 and up:
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 withseek(0, 2)
).
This is because text files do not have a 1-to-1 correspondence between encoded bytes and the characters they represent, so seek
can't tell where to jump to in the file to move by a certain number of characters.
If your program is okay with working in terms of raw bytes, you can change your program to read:
f = open('D:\SGStat.txt', 'ab')
f.seek(-3, 2)
Note the b
in the mode string, for a binary file. (Also note the removal of the redundant f.seek(0, 2)
call.)
However, you should be aware that adding the b
flag when you are reading or writing text can have unintended consequences (with multibyte encoding for example), and in fact changes the type of data read or written.