if statement in opening a file indention

Question:

Dear community I have a problem that although it’s seems to be not a big deal, it took away sleep from me.
and I don’t need sleep, I NEED answer!

I want to open a file, and if the string "MODIFIED" was in the file’s content, I want to print(‘already modified’), then printing the content of the file
here is my code:

with open(f"contents\docs.txt", "r") as f:
    if "MODIFIED" in f.readlines():
        print("already modified")
    
    print(f.readlines())
    print()

it’s seems to be ok, but the weird part is, the file does not contain the string "MODIFIED", so it’s just have to normally print the content of the file, but is only return a empty list [] !
(The file is not empty!)
and if I run it without the if statement, it will normally return the content as it should.

with open(f"contents\docs.txt", "r") as f:
    #if "MODIFIED" in f.readlines():
        #print("already modified")
    
    print(f.readlines())
    print()

I just don’t get it, what does a if statement do to the code that the code return empty list.

  • the doc.txt file that I want to return it’s content
before the flood
david attenborough: a life on our planet
an inconvenient truth
home 2009
kiss the ground 2020
seaspiracy 2020
cosmos

it’s the first time I’m encountering this, idk what to call it, bug?
I would appreciate if you guys help me find out what’s going wrong

Asked By: Argon Ar

||

Answers:

When you read from a file, it saves where you left off. readlines reads the whole file, so when you call readlines again, there is nothing left to read. Store it in a variable:

with open(f"contents\docs.txt", "r") as f:
    lines = f.readlines()
    if "MODIFIED" in lines:
        print("already modified")
    print(lines)

Note: this still won’t work unless you strip off the trailing 'n's at the end of each line. An alternative is to join lines by a n so you get a string not a list.

with open(f"contents\docs.txt", "r") as f:
    lines = f.readlines()
    if "MODIFIED" in 'n'.join(lines):
        print("already modified")
    print(lines)

However, this is not good practice, so this is another alternative:

with open(f"contents\docs.txt", "r") as f:
    lines = f.read().splitlines()
    if "MODIFIED" in lines:
        print("already modified")
    print(lines)

splitlines does not have the trailing n.

Answered By: The Thonnu

"MODIFIED" in f.readlines() will always evaluate to False since "MODIFIED" is a string while f.readlines() is a list of str. Therefore it will compare "MODIFIED" with every element of that list.
As stated by This Answer readlines would also add the trailing n for each line, so even if your file contains MODIFIED it would actually be read as MODIFIEDn, which makes the evaluation come to False. However as pointed out in the comments by Aran-Fey the evaluation can become True if MODIFIED was the last line in the file and there was no newline at the end.

A trailing n would not affect your comparison if you were comparing a string against another as in checks for in and not for equality, which is what = does. Therefore "MODIFIED" in "IAMAMODIFIEDSTRING" is True.

The right thing to do would be to replace it with in f.read() which makes the solution as follows:

with open(f"contents\docs.txt", "r") as f:
    data = f.read()
    if "MODIFIED" in data:
        print("already modified")
    
    print(data)
    print()

However, if you want to make sure MODIFIED is on a line on its own then you would do:

with open(f"contents\docs.txt", "r") as f:
    data = f.readlines()
    if "MODIFIED" in [line.strip() for line in data]:
        print("already modified")
    
    print('n'.join(data))
    print()
Answered By: thethiny
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.