Here's a way to do it without reading the whole file into memory all at once. It does require first reading the whole file, but only storing where each line starts. Once that is known, it can use the seek()
method to randomly access each one in any order desired.
Here's an example using your input file:
# Preprocess - read whole file and note where lines start.
# (Needs to be done in binary mode.)
with open('text_file.txt', 'rb') as file:
offsets = [0] # First line is always at offset 0.
for line in file:
offsets.append(file.tell()) # Append where *next* line would start.
# Now reread lines in file in reverse order.
with open('text_file.txt', 'rb') as file:
for index in reversed(range(len(offsets)-1)):
file.seek(offsets[index])
size = offsets[index+1] - offsets[index] # Difference with next.
# Read bytes, convert them to a string, and remove whitespace at end.
line = file.read(size).decode().rstrip()
print(line)
Output:
2018/03/26-15:08:51.066968 1 7FE9BDC91700 std:ZMD:
2018/03/26-10:08:51.066967 0 7FE9BDC91700 Exit Status = 0x0
2018/03/26-00:08:50.981908 1389 7FE9BDC2B707 user 7fb31ecfa700
2018/03/25-24:08:50.980519 16K 7FE9BD1AF707 user: number is 93823004
2018/03/25-20:08:50.486601 1.5M 7FE9D3D41706 qojfcmqcacaeia
2018/03/25-10:08:48.985053 346K 7FE9D2D51706 ahelooa afoaona woom
2018/03/25-00:08:48.638553 508 7FF4A8F3D704 snononsonfvnosnovoosr
Update
Here's a version that does the same thing but uses Python's mmap
module to memory-map the file which should provide better performance by taking advantage of your OS/hardware's virtual-memory capabilities.
This is because, as PyMOTW-3 put's it:
Memory-mapping typically improves I/O performance because it does not involve a separate system call for each access and it does not require copying data between buffers – the memory is accessed directly by both the kernel and the user application.
Code:
import mmap
with open('text_file.txt', 'rb') as file:
with mmap.mmap(file.fileno(), length=0, access=mmap.ACCESS_READ) as mm_file:
# First preprocess the file and note where lines start.
# (Needs to be done in binary mode.)
offsets = [0] # First line is always at offset 0.
for line in iter(mm_file.readline, b""):
offsets.append(mm_file.tell()) # Append where *next* line would start.
# Now process the lines in file in reverse order.
for index in reversed(range(len(offsets)-1)):
mm_file.seek(offsets[index])
size = offsets[index+1] - offsets[index] # Difference with next.
# Read bytes, convert them to a string, and remove whitespace at end.
line = mm_file.read(size).decode().rstrip()
print(line)