Skip to content

Instantly share code, notes, and snippets.

@f3rdy
Created August 3, 2016 06:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save f3rdy/32c0b7fb3ee2bf1db0c0c03977f21377 to your computer and use it in GitHub Desktop.
Save f3rdy/32c0b7fb3ee2bf1db0c0c03977f21377 to your computer and use it in GitHub Desktop.
reverse readline
import os
# from: http://bit.ly/2arGvvk
def reverse_readline(filename, buf_size=8192):
"""a generator that returns the lines of a file in reverse order"""
with open(filename) as fh:
segment = None
offset = 0
fh.seek(0, os.SEEK_END)
file_size = remaining_size = fh.tell()
while remaining_size > 0:
offset = min(file_size, offset + buf_size)
fh.seek(file_size - offset)
buffer = fh.read(min(remaining_size, buf_size))
remaining_size -= buf_size
lines = buffer.split('\n')
# the first line of the buffer is probably not a complete line so
# we'll save it and append it to the last line of the next buffer
# we read
if segment is not None:
# if the previous chunk starts right from the beginning of line
# do not concact the segment to the last line of new chunk
# instead, yield the segment first
if buffer[-1] is not '\n':
lines[-1] += segment
else:
yield segment
segment = lines[0]
for index in range(len(lines) - 1, 0, -1):
if len(lines[index]):
yield lines[index]
# Don't yield None if the file was empty
if segment is not None:
yield segment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment