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 yourreadlines()
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