Python readlines not returning anything?

I have the following code:

with open('current.cfg', 'r') as current:
    if len(current.read()) == 0:
        print('FILE IS EMPTY')
    else:
        for line in current.readlines():
            print(line)

The file contains this:

#Nothing to see here
#Just temporary data
PS__CURRENT_INST__instance.12
PS__PREV_INST__instance.16
PS__DEFAULT_INST__instance.10

For some reason though, current.readlines() just returns an empty list every time.

There is probably a stupid mistake or typo in the code, but I just cannot find it. Thanks in advance.


Solution 1:

You read the file already, and the file pointer is not at the end of the file. Calling readlines() then will not return data.

Read the file just once:

with open('current.cfg', 'r') as current:
    lines = current.readlines()
    if not lines:
        print('FILE IS EMPTY')
    else:
        for line in lines:
            print(line)

The other option is to seek back to the start before reading again:

with open('current.cfg', 'r') as current:
    if len(current.read()) == 0:
        print('FILE IS EMPTY')
    else:
        current.seek(0)
        for line in current.readlines():
            print(line)

but that's just wasting CPU and I/O time.

The best approach would be to try and read a small amount of data, or seek to the end, take the file size by using file.tell() and then seek back to the start, all without reading. Then use the file as an iterator to prevent reading all the data into memory. That way you don't produce memory problems when the file is very large:

with open('current.cfg', 'r') as current:
    if len(current.read(1)) == 0:
        print('FILE IS EMPTY')
    else:
        current.seek(0)
        for line in current:
            print(line)

or

with open('current.cfg', 'r') as current:
    current.seek(0, 2)  # from the end
    if current.tell() == 0:
        print('FILE IS EMPTY')
    else:
        current.seek(0)
        for line in current:
            print(line)

Solution 2:

When you do current.read(), you consume the contents of the file, so a subsequent current.readlines() returns an empty list.

Martijn Pieters's code is the way to go.

Alternatively, you could do rewind to the beginning of the file with a current.seek(0) before the readlines(), but this is unnecessarily complicated.