how to save changes after modifying content in file using Python - python

I want to insert a line into file "original.txt" (the file contains about 200 lines). the line neds to be inserted two lines after a string is found in one of the existing lines. This is my code, I am using a couple of print options that show me that the line is being added to the list, in the spot I need, but the file "original.txt" is not being edited
with open("original.txt", "r+") as file:
lines = file.readlines() # makes file into a list of lines
print(lines) #test
for number, item in enumerate(lines):
if testStr in item:
i = number +2
print(i) #test
lines.insert(i, newLine)
print(lines) #test
break
file.close()
I am turning the lines in the text into a list, then I enumerate the lines as I look for the string, assigning the value of the line to i and adding 2 so that the new line is inserted two lines after, the print() fiction shows the line was added in the correct spot, but the text "original.txt" is not modified

You seem to misunderstand what your code is doing. Lets go line by line
with open("original.txt", "r+") as file: # open a file for reading
lines = file.readlines() # read the contents into a list of lines
print(lines) # print the whole file
for number, item in enumerate(lines): # iterate over lines
if testStr in item:
i = number +2
print(i) #test
lines.insert(i, newLine) # insert lines into the list
print(lines) #test
break # get out of the look
file.close() # not needed, with statement takes care of closing
You are not modifying the file. You read the file into a list of strings and modify the list. To modify the actual file you need to open it for writing and write the list back into it. Something like this at the end of the code might work
with open("modified.txt", "w") as f:
for line in lines: f.write(line)

You never modified the original text. Your codes reads the lines into local memory, one at a time. When you identify your trigger, you count two lines, and then insert the undefined value newLine into your local copy. At no point in your code did you modify the original file.
One way is to close the file and then rewrite it from your final value of lines. Do not modify the file while you're reading it -- it's good that you read it all in and then start processing.
Another way is to write to a new file as you go, then use a system command to replace the original file with your new version.

Related

Index Error When Deleting Lines From A txt File

lines = file.readlines()
del lines[68]
This is the code im using to delete the lines, I have already opened the file it works with lots of other stuff. When I run this code it pops up with an index error when Im deleting lines in the middle of the txt file. I ve tried many versions of deleting lines in the txt file but none of them work. Any ideas?
In short
You can add f.seek(0) before f.readlines(), and try your code again.
Long explain
I tried your code and it seems working normally when deleting single element in lines.
Did you use f.readlines() multiple times? In that case, the second time this method will return empty list because the first call already move the cursor to end of file.
To read the file again, you have to use this method f.seek(0) to move the cursor back to the begin of file before calling f.readlines()
How about testing if the txt file has 69 lines at all ?
def delete_line(path, number)
f = opne(path, "r")
lines = f.readlines()
f.close()
if len(lines) - 1 < number:
print("The file %s has not a line number %d" % (path, number))
else:
del lines[number]
return lines
Use it like this:
lines = delete_line("path/to/file/you/want/to/delete/a/line/from.txt", 68)
If your file was long enough, you will have the file minus the specified line saved in lines, else a warning will be printed and the value of lines will be the unmodified file.

How do I remove the "\n" characters when reading my file but deleting one variable then replacing it

I am trying to make a program that reads from a file and deletes one specific line inside of it and then puts all the data stored back to the file separated with a new line. The file uses this format:
Jones|20|20|00
bob|30|19|90
James|40|19|80
So I want to delete (backup contains this and is the line I want to delete)
bob|30|19|90
but the code that I am using takes away the new line and doesnt replace it but when I try to add \n to it the file doesn't want to read as it does this (adds 2 "\n"s):
Jones|20|20|00
James|40|19|80
I am using this code below:
def deleteccsaver(backup):
lockaccount =""
lockaccount = lockaccount.strip("\n")
with open('accounts_project.txt','r+') as f:
newline=[]
for line in f.readlines():
newline.append(line.replace(backup, lockaccount).strip("\n"))
with open('accounts_project.txt','w+') as f:
for line in newline:
f.writelines(line +"\n")
f.close()
resetlogin()
Please help as I dont know how to add the \n back without it appearing as "\n\n"
Without the "\n "it appears as:
Jones|20|20|00James|40|19|80
Any suggestions:
What I am doing here is reading the entire file at once, please don't do this if you have a very very big file. After reading all file contents at once, I am making a list out of it using "\n" as a delimiter. Read about split function in python to know more about it. Then from the list I am replacing the backup with lockaccount, as you have been doing the same, these are the names of variables that you are using, hope I did not confuse between them in this case. Then it will be saved to a new file after adding new line after each element of list, i.e. each line of the previous file. This will cause the result file to have all the contents as previous file, but removing what you wanted to remove. I see that lockaccount is itself an empty string, so adding it might create a newline in your file. In case you dont want lockaccount to replace the backup variable in the file, just remove the backup from the list using contents.remove(backup) instead of contents[contents.index(backup)] == lockaccount keeping the rest of the code same. Hope this explains better.
def deleteccsaver(backup):
lockaccount =""
lockaccount = lockaccount.strip("\n")
with open('accounts_project.txt','r+') as f:
contents = f.read().split("\n")
if backup in contents:
contents[contents.index(backup)] = lockaccount
new_contents = "\n".join(contents)
with open('accounts_project.txt','w+') as f:
f.write(new_contents)
resetlogin()
You are priting a newline character after each element in the list. So, if you replace a line with the empty string, well, you will get an empty line.
Try to simply skip over the line you want to delete:
if line == backup:
contiune
else:
lines.append(...)
PS. There is room for improvment in the code above, but I'm on the phone, I will get back with an edit later if nobody gets ahead of me
You can try to add newline = '\n'.join(newline) after your first for loop and then just write it into the accounts_project.txt file without a loop.
The code should then look like:
def deleteccsaver(backup):
lockaccount =""
lockaccount = lockaccount.strip("\n")
with open('accounts_project.txt','r+') as f:
newline=[]
for line in f.readlines():
newline.append(line.replace(backup, lockaccount).strip("\n"))
newline = '\n'.join(newline)
with open('accounts_project.txt','w+') as f:
f.write(newline)
f.close() # you don't necessarily need it inside a with statement
resetlogin()
Edit:
Above code still results in
Jones|20|20|00
James|40|19|80
as output.
That's because during the replacement loop an empty string will be appended to newline (like newline: ['Jones|20|20|00','','James|40|19|80']) and newline = '\n'.join(newline) will then result in 'Jones|20|20|00\n\nJames|40|19|80'.
A possible fix can be to replace:
for line in f.readlines():
newline.append(line.replace(backup, lockaccount).strip("\n"))
with
for line in f.readlines():
line = line.strip('\n')
if line != backup:
newline.append(line)
def deleteccsaver(backup):
lockaccount =""
lockaccount = lockaccount.strip("\n")
with open('accounts_project.txt','r+') as f:
contents = f.read().split("\n")
if backup in contents:
contents.remove(backup)
new_contents = "\n".join(contents)
with open('accounts_project.txt','w+') as f:
f.write(new_contents)
resetlogin()

How do I make a list from a textfile in Python?

I have a txt file that contains names which are separated by lines but with some empty lines.
When I execute the following code, every second name gets ommitted in the output array.
Why is that?
def get_string_list(string_textfile):
list = []
file = open("names.txt", "r")
for line in file:
line = file.readline()[:-1]
list.append(line.lower())
return list
when you iterate the file
for line in file:
# you read line just now it exists
line = file.readline()
# uh oh you just read another line... you didnt do anything with the first one
dont mix iteration of a file with readline in general (in fact i think modern python versions will throw an error if you try to mix these two)
if all you want is a list of lines you can do any of the following
lines = list(file)
# or
lines = file.readlines()
you can get only non_empty lines and strip newlines as follows
lines_stripped = list(filter(None,(l.strip() for l in file)))
not super pythonic but its nice and terse and pretty clear what its doing
modify for statements like following:
for line in file:
list.append(line.strip().lower())
list = [name for name in list if name]
last line added to remove empty line.

While in python does not print all the rows

Dear I want display the three rows contained in txt file but I don't know why the following code does not works.
The code is
f=open("dati.txt","r")
riga=f.readline()
while riga!="":
print(f.readline())
riga=f.readline()
f.close()
because you are reading two lines in a loop. The readline moves the cursor one down each time you call it. So what happens there with the second call of readline() you actually skip it(in the print log)
Also checking for end of file should not be done on empty string, because you may hit an empty line before the end of the file. Try this instead:
with open('somefile') as openfileobject:
for line in openfileobject:
do_something()
and or/check this thread(where I copied the snippet from): What is the perfect counterpart in Python for "while not EOF"
The reason why your program is not printing all the rows in the file, but rather only every even numbered row, is because you use f.readline() multiple times in the while statement.
f=open("dati.txt","r")
riga=f.readline() # This line means that the variable "riga" contains the first line in your file
while riga!="":
print(f.readline()) # here you do f.readline() again, which means that what you are printing is the second line
riga=f.readline() # This line reads in the third line into the "riga" variable.
f.close()
What I think you are looking for, is to print the contents of the riga variable instead, like this
while riga != "":
print(riga)
riga = f.readline()
I should also mention that tstoev's answer also has a good approach at printing each line in a file. It does solve the same problem, but it does not point out why your code doesn't work.
Your code reads three lines and prints only one:
f=open("dati.txt","r")
riga=f.readline() # Reads a line into riga
while riga!="":
print(f.readline()) # Reads a line and prints it
riga=f.readline() # Reads a line into riga
f.close()
So the problem seems that you read lines into riga, but never print riga.

Replace only first line of text file in python

I have a text file which consists of many lines of text.
I would like to replace only the first line of a text file using python v3.6 regardless of the contents. I do not need to do a line-by-line search and replace the line accordingly. No duplication with question Search and replace a line in a file in Python
Here is my code;
import fileinput
file = open("test.txt", "r+")
file.seek(0)
file.write("My first line")
file.close()
The code works partially. If the original first line has string longer than "My first line", the excess sub-string still remains. To be clearer, if original line is "XXXXXXXXXXXXXXXXXXXXXXXXX", then the output will be "My first lineXXXXXXXXXXXXXX". I want the output to be only "My first line". Is there a better way to implement the code?
You can use the readlines and writelines to do this.
For example, I created a file called "test.txt" that contains two lines (in Out[3]). After opening the file, I can use f.readlines() to get all lines in a list of string format. Then, the only thing I need to do is to replace the first element of the string to whatever I want, and then write back.
with open("test.txt") as f:
lines = f.readlines()
lines # ['This is the first line.\n', 'This is the second line.\n']
lines[0] = "This is the line that's replaced.\n"
lines # ["This is the line that's replaced.\n", 'This is the second line.\n']
with open("test.txt", "w") as f:
f.writelines(lines)
Reading and writing content to the file is already answered by #Zhang.
I am just giving the answer for efficiency instead of reading all the lines.
Use: shutil.copyfileobj
from_file.readline() # and discard
to_file.write(replacement_line)
shutil.copyfileobj(from_file, to_file)
Reference

Categories

Resources