Reputation: 31
I have a file called inputs.txt and I am trying to replace a string in that file with the value of a function. The problem is I am not able to write to that file. I just started learning python so struggling with this. Any help please.
When I have it as a string it works fine
Content of the file
[aws_s3://MAC_10]
key_name = ABC/YYZZ/daily
Desired output
[aws_s3://MAC_2014-12-31]
key_name = ABC/YYZZ/daily/2014-12-31_
I wrote the function which gets the time value as
def change_time(match):
match = match.group()
date_time = datetime.datetime.now()
value = str(date_time.strftime('%Y-%m-%d'))
return value
I was able to open the file and read and match content but I am not able to write to it
f=open('test.txt','w')
print re.sub(r'_[0-9-]+',change_time,string)
outputs the required changed first line to stdout, but how do I modify the contents of the file?
Upvotes: 1
Views: 382
Reputation: 3433
If you have not programmed much, it might be easy to think of a file as it is seen in an editor, where you can position your cursor at a particular point and insert characters at that point, causing other characters in the file to "slide to the right". Writing to a file does not work this way. Instead, writing a file at a particular point deletes all file contents after that point, meaning that you need to read the whole file into memory, modify the contents of the file, and then write the contents back out to the file.
More specifically, since the file will have a different number of bytes in it after your modifications, and all the insertion/deletion of characters do not happen at the end of the file, here is the procedure you generally want to follow:
First, you read the entire contents of the file into memory, something like
import io
with io.open('file.ini') as fobj:
contents = fobj.read()
Note that after this code has run, the file is closed again: you have copied the contents of the file into memory, and the file remains unchanged on disk.
Next, you modify the contents of the file in your desired way
def change_time(match):
match = match.group()
date_time = datetime.datetime.now()
value = str(date_time.strftime('%Y-%m-%d'))
return value
new_contents = re.sub(r'_[0-9-]+',change_time,contents)
Now, you re-open the file in write mode. This immediately throws away the contents of the file, and you write back your own (now modified) copy from memory
with io.open('file.ini','wb') as fobj:
fobj.write(new_contents)
Upvotes: 1
Reputation: 882291
Reading and writing the same file can be tricky, but the fileinput
module of the standard library supports that well:
import fileinput
for line in fileinput.input(['inputs.txt'], inplace=True):
print re.sub(r'_[0-9-]+', change_time, line) ,
I'm giving the Python 2 form of print
because it seems that's what you're using. Anyway, in Python 3 it would be similar and more readable:
print(re.sub(r'_[0-9-]+', change_time, line), end='')
At any rate, fileinput
redirects standard output so that all print
s go to the very file you're reading (when the inplace=True
has been set) -- you need to print out all you're reading in, with changes were needed. Works on as many files as you need (note that the first argument is a list of filenames), no matter how big they are, etc, etc.
See https://docs.python.org/2/library/fileinput.html for much, much more:-)
Upvotes: 3
Reputation: 11728
The solution is to read in value, edit change in memory and write our new value
contents = open('file.ini').read()
contents = re.sub(r'_[0-9-]+',change_time,contents)
with open('file.ini', 'w') as fout:
fout.write(contents)
Upvotes: 0