Reputation: 14108
I'm looking to load a file and modify several predefined lines to certain values. The following is what I tried:
with open("test.txt",'w') as f:
for i,line in f:
if (i == 2):
f.writelines(serial1)
if (i == 3):
f.writelines(serial2)
if (i == 4):
f.writelines(serial3)
else:
f.writelines(line)
However, when running the code I got the following error:
for i,line in f:
io.UnsupportedOperation: not readable
What am I doing wrong?
Upvotes: 0
Views: 75
Reputation: 110311
You open the file for write-only (w
mode) and try to read it - which is done by the for
statement.
That is: iterating over a file with the for
statement is done when you are reading the file.
If you plan to write to it, for
on the fileitself can't help you - just use a normal counter with "range" and write to it.
with open("test.txt",'w') as f:
for i in range(desired_lines):
if (i == 2):
f.write(serial1 + "\n")
if (i == 3):
f.write(serial2 + "\n")
if (i == 4):
f.write(serial3 + "\n")
else:
f.write(line + "\n")
Also, writelines
should be used when you have a list of strings you want to write,
each ina separate line - yu don't show the content of your vaiables, but given that you want the exact line numbers, it looks like writelines
is not what you want.
(On a side note - beware of indentation - you should ident a fixed ammount foreach block you enter in Python - it will work with an arbitrry identation like you did, but is not usual in Python code)
update It looks like you need to change just some lines of an already existing text file. The best approach for this is by far to recreate another file, replacing the lines you want, and rename everything afterwards. (Writing over a text file is barely feasible, since all text lines would have to be the same size as the previously existing lines - and still would gain nothing in low-level disk access).
import os
...
lines_to_change{
2: serial1,
3: serial2,
4: serial3,
}
with open("test.txt",'rt') as input_file, open("newfile.txt", "wt") as output_file:
for i, line in enumerate(input_file):
if i in lines_to_change:
output_file.write(lines_to_change[i] + '\n')
else:
output_file.write(line)
os.rename("test.txt", "test_old.txt")
os.rename("newfile.txt", "test.txt")
os.unlink("test_old.txt")
Upvotes: 1
Reputation: 40733
What you are doing is called editing in place. For that, Python standard library fileinput
can help:
import fileinput
for line in fileinput.input('test.txt', inplace=True):
if fileinput.lineno() == 2:
print serial1
elif fileinput.lineno() == 3:
print serial2
elif fileinput.lineno() == 4:
print serial3
else:
print line
As for "What I'm doing wrong?" there are a couple:
fileinput
as shown above.for i, line in f
does not work, I think you meant for i, line in enumerate(f, 1)
if
statement should be if ... elif ... else
. Currently your else clause is attached only to the if i == 4
statement, not the other two.Upvotes: 2
Reputation: 11220
As pointed out, your issue is that you try to read and write in the same file. The easiest way is to open a new file, and replace the first one when you have the desired output.
To get the file lines number, you can use enumerate:
with open("test.txt",'r') as f:
for i,line in enumerate(f):
if (i == 2):
f.writelines(serial1)
if (i == 3):
f.writelines(serial2)
if (i == 4):
f.writelines(serial3)
else:
f.writelines(line)
Upvotes: 0