Check if value exists in file

I would consider several changes.

1: Use with to automatically close the file.
2: Use strip() to remove leading or trailing stuff, like \n
3: Use a break for the loop.
4: Add \n in the write part.

value = "345"
with open("file.txt", "a+") as file:
    file.seek(0)
    for line in file.readlines():
        if line.strip("\n") == value:
            print('val ready exists in file')
            break
    else:
        # write to file
        file.write(f"\n{value}")

Since you want to open the file for reading and writing, I suggest using the r+ mode from open(). This will open the file at the beginning of the file, since we want to first read all lines. Using a+ will open the file for reading and writing at the end of the file, which will cause lines to give you an empty list from readlines().

You also need to strip newlines from lines before checking if the value exists. This is because 345 is not equal to 345/n. We can use a list comprehension to strip the newlines from lines using str.rstrip(), which strips whitespace from the right. Additionally, If you have to do repetitive lookups for multiple values, it might be worth converting lines to a set for constant time lookups, instead of doing a linear search with a list.

Its also worth using With Statement Context Managers when reading files, since the closing of the file is handled for you.

value = '345'

with open("file.txt", mode="r+") as file:
    lines = [line.rstrip() for line in file.readlines()]

    if value in lines:
        print('value ready exists in file')
    else:
        file.write(f"{value}\n")

The other choice is to use f.seek(0) with a+ to set the position at the beginning of the file, as shown in @Cihan Ceyhan's answer. However I think this overcomplicates things, and its just easier to use the r+ mode.


There are two problems here:

  • .readlines() returns lines with \n not trimmed, so your check will not work properly.
  • a+ mode opens a file with position set to the end of the file. So your readlines() currently returns an empty list!

Here is a direct fixed version of your code, also adding context manager to auto-close the file

value = '345'
with open("file.txt", "a+") as file:
    file.seek(0) # set position to start of file
    lines = file.read().splitlines() # now we won't have those newlines
    if value in lines:
        print('val ready exists in file')
    else:
        # write to file
        file.write(value + "\n") # in append mode writes will always go to the end, so no need to seek() here

However, I agree with @RoadRunner that better is to just use r+ mode; then you don't need the seek(0). But the cleanest is just to split out your read and write phases completely, so you don't run into file position problems.


when working with io the recomended approach is to use the context manager. Context managers allow you to allocate and release resources precisely when you want to. The most widely used example of context managers is the with statement. if you have a large file better not to use file.readlines() or the read() method. The readlines() method returns a list containing each line in the file as a list item. better to iterate on the file stream line by line (generator). always use try except with io operations! :

values=['123','233'...]
try:
    with open("file.txt", "r+") as fp:
        for line in fp:
            for val in values:
                if val not in line.strip():
                    fp.write(val)
                else:
                    print('val ready exists in file')
except (OSError,...): #catch what ever you think this code above can raise, and re raise in except block if you want.
#do exception handling