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 by tell()
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