'Script to read file and print first two and last two lines of it

I'm writing a program where the user inputs a file name and then the file and prints only the first 2 and the last 2 lines of the file. I have worked out how to print the first two lines and I have tried to print the last two lines but have hit a hiccup. Is anyone able to explain what I did wrong?

f1 = open(input("Source file name: "))

line1= f1.readline()
line2= f1.readline()
line12= f1.readline()
line13= f1.readline()
print("Output:",line1,line2,line12[-1],line13[-2], sep= "")
f1.close()

The file is 13 lines long so the output should be as follows:

output:
line 1
line 2
line 12
line 13


Solution 1:[1]

You're reading the first 4 lines. You need to read through all of them and keep only the last two.

This code reads through all of them, saving the last two lines read:

line1 = f1.readline()
line2 = f1.readline()

last1, last2 = f1.readline(), f1.readline()
while True:
    line = f1.readline()
    if not line:  # eof
        break
    last1, last2 = line, last1

print("Output:",line1,line2,last2,last1, sep= "")

For example, with a file test.txt:

Line1
line2
Line3
line4
Line5
line6
last line, line 7

You get:

Output:Line1
line2
line6
last line, line 7

Solution 2:[2]

Your line12 and line13 are strings, not lists. So even if they had the right contents, by indexing into them you're only printing a single character. That's certainly not what you want.

For a short file like your stated example, the easiest thing is to read the entire file into a list of lines.

with open(input("Source file name: ")) as f1:
    lines = f1.readlines()
print("Output:",lines[0],lines[1],lines[-2],lines[-1], sep= "")

For a larger file, that approach will be slow and could make you run out of memory. If you know the longest length of a line, you could seek to near the end of the file and just read the last lines of the file separately. I'm not going to give the code for that since it doesn't apply in your case.

Solution 3:[3]

You could use next() on the file object iterator to get the first 2 lines, then use a deque() as a circular buffer to capture the last 2 lines. This will work with files that are less than 4 lines or no lines also!

from collections import deque


with open("test.txt") as f_in:

    print(next(f_in, ""), end="")
    print(next(f_in, ""), end="")

    buffer = deque(maxlen=2)
    for line in f_in:
        buffer.append(line)

    for line in buffer:
        print(line, end="")

text.txt

1
2
3
4
5
6
7
8
9
10

Output:

1
2
9
10

Solution 4:[4]

simple way to do it!

with open("test.txt") as f:
    lines = f.read().split("\n")
    last1 = lines[len(lines)-1]
    last2 = lines[len(lines)-2]
    first1 = lines[0]
    first2 = lines[1]

learn more about read and split

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Eric Jin
Solution 2 Mark Ransom
Solution 3 Terry Spotts
Solution 4 Brian None