Read and overwrite a file in Python - python

Currently I'm using this:
f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.close()
But the problem is that the old file is larger than the new file. So I end up with a new file that has a part of the old file on the end of it.

If you don't want to close and reopen the file, to avoid race conditions, you could truncate it:
f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.truncate()
f.close()
The functionality will likely also be cleaner and safer using open as a context manager, which will close the file handler, even if an error occurs!
with open(filename, 'r+') as f:
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.truncate()

The fileinput module has an inplace mode for writing changes to the file you are processing without using temporary files etc. The module nicely encapsulates the common operation of looping over the lines in a list of files, via an object which transparently keeps track of the file name, line number etc if you should want to inspect them inside the loop.
from fileinput import FileInput
for line in FileInput("file", inplace=1):
line = line.replace("foobar", "bar")
print(line)

Probably it would be easier and neater to close the file after text = re.sub('foobar', 'bar', text), re-open it for writing (thus clearing old contents), and write your updated text to it.

I find it easier to remember to just read it and then write it.
For example:
with open('file') as f:
data = f.read()
with open('file', 'w') as f:
f.write('hello')

To anyone who wants to read and overwrite by line, refer to this answer.
https://stackoverflow.com/a/71285415/11442980
filename = input("Enter filename: ")
with open(filename, 'r+') as file:
lines = file.readlines()
file.seek(0)
for line in lines:
value = int(line)
file.write(str(value + 1))
file.truncate()

Honestly you can take a look at this class that I built which does basic file operations. The write method overwrites and append keeps old data.
class IO:
def read(self, filename):
toRead = open(filename, "rb")
out = toRead.read()
toRead.close()
return out
def write(self, filename, data):
toWrite = open(filename, "wb")
out = toWrite.write(data)
toWrite.close()
def append(self, filename, data):
append = self.read(filename)
self.write(filename, append+data)

Try writing it in a new file..
f = open(filename, 'r+')
f2= open(filename2,'a+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.close()
f2.write(text)
fw.close()

Related

How to append text into a variable in a different python file?

I'm trying to make a code that would take the information a user inputs and adds it permanently to a different file's variable:
main.py:
text = "hello world"
f = open("Testfile.py", "a+")
f.write(text)
Testfile.py:
w = ["bob", "joe", "emily"]Hello World
how can I make it so that "Hello World" would appear in w such as
w = ["bob", "joe", "emily", "Hello World"]
Edit:
what if w is a library such as
w = {"bob": 0, "joe": 0, "emily" : 0}
and I want to add "Hello World" : 0 to it
Is it really necessary to store the content of you array to a python file?
You could store it into a yaml file for instance instead, and you a yaml library to write and read the content to/from that file.
import yaml
import os
def load_yaml(filename):
with open(filename, 'r') as fp:
y = yaml.safe_load(fp)
return y
def save_yaml(content, filename):
if os.path.exists(filename):
os.remove(filename)
with open(filename, 'w') as fp:
yaml.safe_dump(content, fp, default_flow_style=False)
w = ["bob", "joe", "emily"]
save_yaml(w, "data.yaml")
w.append("hello world")
save_yaml(w, "data.yaml")
content = load_yaml("data.yaml")
print(content)
I would strongly recommend not modifying a python file programmatically. You will likely be able to accomplish the same task by storing your list in a text file and having any program read the text file and build the list. There are other file formats you could use for more complicated tasks, but for simply putting strings in a list this code is sufficient. Some kind of full-on database would be best for a real-world application.
test.txt:
bob
joe
emily
main.py:
def read_file():
f = open('test.txt', 'r')
lines = f.readlines()
lines = [line.strip() for line in lines] #removes the '\n' character at the end of each line
print(lines)
f.close()
def append_file(item):
f = open('test.txt', 'a')
f.write(item)
f.write('\n')
f.close()
read_file()
append_file("Hello World")
append_file("test")
read_file()
Also as a bonus, you can use with to manage file objects more concisely.
def read_file():
with open('test.txt', 'r') as f:
lines = f.readlines()
lines = [line.strip() for line in lines] #removes the '\n' character at the end of each line
print(lines)
def append_file(item):
with open('test.txt', 'a') as f:
f.write(item)
f.write('\n')

Append and Read Same File - Python

Stuck on this school question, what am I missing?
"Objective: Complete the function to append the given new data to the specified file then print the contents of the file"
On of my many attempts:
import os
def appendAndPrint(filename, newData):
with open(filename, 'a') as f:
f = f.write(newData)
r = f.read()
print(r)
Test case, expected output: Hello World
with open("test.txt", 'w') as f:
f.write("Hello ")
appendAndPrint("test.txt", "World")
If I get the interpreter to not throw an error, on several attempts it would simply print 5.
This code should work:
def append_and_print(filename, new_data):
with open(filename, "a") as f:
f.write(new_data)
with open(filename, "r") as f:
print(f.read())
You can open the file with a+ to also give your program read permissions:
import os
def appendAndPrint(filename, newData):
with open(filename, 'a+') as f:
f.write(newData)
f.seek(0)
r=f.read()
print(r)
...
edit: as commenters pointed out, you need to seek to the 0 position in the file so that you can read the whole thing
You can use a+ mode for reading/writing.
After you append using write,
you can move the cursor to the initial position using seek method,
then read it from the beginning.
def appendAndPrint(filename, newData):
with open(filename, 'a+') as f:
f.write(newData)
f.seek(0)
print(f.read())
with open("test.txt", 'w') as f:
f.write("Hello ")
appendAndPrint("test.txt", "World")
Hello World

How to write to a CSV line by line?

I have data which is being accessed via http request and is sent back by the server in a comma separated format, I have the following code :
site= 'www.example.com'
hdr = {'User-Agent': 'Mozilla/5.0'}
req = urllib2.Request(site,headers=hdr)
page = urllib2.urlopen(req)
soup = BeautifulSoup(page)
soup = soup.get_text()
text=str(soup)
The content of text is as follows:
april,2,5,7
may,3,5,8
june,4,7,3
july,5,6,9
How can I save this data into a CSV file.
I know I can do something along the lines of the following to iterate line by line:
import StringIO
s = StringIO.StringIO(text)
for line in s:
But i'm unsure how to now properly write each line to CSV
EDIT---> Thanks for the feedback as suggested the solution was rather simple and can be seen below.
Solution:
import StringIO
s = StringIO.StringIO(text)
with open('fileName.csv', 'w') as f:
for line in s:
f.write(line)
General way:
##text=List of strings to be written to file
with open('csvfile.csv','wb') as file:
for line in text:
file.write(line)
file.write('\n')
OR
Using CSV writer :
import csv
with open(<path to output_csv>, "wb") as csv_file:
writer = csv.writer(csv_file, delimiter=',')
for line in data:
writer.writerow(line)
OR
Simplest way:
f = open('csvfile.csv','w')
f.write('hi there\n') #Give your csv text here.
## Python will convert \n to os.linesep
f.close()
You could just write to the file as you would write any normal file.
with open('csvfile.csv','wb') as file:
for l in text:
file.write(l)
file.write('\n')
If just in case, it is a list of lists, you could directly use built-in csv module
import csv
with open("csvfile.csv", "wb") as file:
writer = csv.writer(file)
writer.writerows(text)
I would simply write each line to a file, since it's already in a CSV format:
write_file = "output.csv"
with open(write_file, "wt", encoding="utf-8") as output:
for line in text:
output.write(line + '\n')
I can't recall how to write lines with line-breaks at the moment, though :p
Also, you might like to take a look at this answer about write(), writelines(), and '\n'.
To complement the previous answers, I whipped up a quick class to write to CSV files. It makes it easier to manage and close open files and achieve consistency and cleaner code if you have to deal with multiple files.
class CSVWriter():
filename = None
fp = None
writer = None
def __init__(self, filename):
self.filename = filename
self.fp = open(self.filename, 'w', encoding='utf8')
self.writer = csv.writer(self.fp, delimiter=';', quotechar='"', quoting=csv.QUOTE_ALL, lineterminator='\n')
def close(self):
self.fp.close()
def write(self, elems):
self.writer.writerow(elems)
def size(self):
return os.path.getsize(self.filename)
def fname(self):
return self.filename
Example usage:
mycsv = CSVWriter('/tmp/test.csv')
mycsv.write((12,'green','apples'))
mycsv.write((7,'yellow','bananas'))
mycsv.close()
print("Written %d bytes to %s" % (mycsv.size(), mycsv.fname()))
Have fun
What about this:
with open("your_csv_file.csv", "w") as f:
f.write("\n".join(text))
str.join() Return a string which is the concatenation of the strings in iterable.
The separator between elements is
the string providing this method.
In my situation...
with open('UPRN.csv', 'w', newline='') as out_file:
writer = csv.writer(out_file)
writer.writerow(('Name', 'UPRN','ADMIN_AREA','TOWN','STREET','NAME_NUMBER'))
writer.writerows(lines)
you need to include the newline option in the open attribute and it will work
https://www.programiz.com/python-programming/writing-csv-files

How can I read individual lines from a CSV file?

At the moment I've got this function:
def writer(file_name)
open_file = open(file_name,"r+", newline='')
csv_output = csv.writer(open_file)
csv_output.writerow(student)
open_file.close()
where student is:
"string_1","string_2",int
I'm looking to read through the file first and check if the "string_1" that I'm writing matches any of the "string_1"s already written, but I can't find a built-in function that lets me read each line and store it as a list.
First, you have to open the file for reading, go through the file line by line and return, if "string_1" is found:
def append_student(file_name, student)
with open(file_name, "r") as f:
for line in csv.reader(f):
if line[0] == student[0]:
return
with open(file_name, "a") as f:
csv.writer(f).writerow(student)

How to add a value to a specific line in a file in python?

I've seen really complex answers on this website as how to edit a specific line on a file but I was wondering if there was a simple way to do it?
I want to search for a name in a file, and on the line that I find that name on, I want to add an integer to the end of the line (as it is a score for a quiz). Or could you tell me how I can replace the entirety of the line with new data?
I have tried a lot of coding but either no change is made, or all of the data in the file gets deleted.
I tried this....
with open ('File.py', 'r') as class_file:
for number, line in enumerate(class_file):
if name in line:
s=open('File.py', 'r').readlines()
s[number]=str(data)
class_file=open('File.py', 'w')
class_file.writelines(new_score)
class_file.close()
As well as this function....
def replace (file, line_number, add_score):
s=open(file, 'w')
new_data=line[line_number].replace(line, add_score)
s.write(str(new_data))
s.close()
As well as this...
def replace_score(file_name, line_num, text):
new = open(file_name, 'r').readlines()
new[line_num] = text
adding_score= open(file_name, 'w')
adding_score.writelines(new)
adding_score.close()
But I still can't get it to work.
The last code works if I'm trying to replace the first line, but not the others.
You need to get the content of the file. Close the file. Modify the content and rewrite the file with the modified content. Try the following:
def replace_score(file_name, line_num, text):
f = open(file_name, 'r')
contents = f.readlines()
f.close()
contents[line_num] = text+"\n"
f = open(file_name, "w")
contents = "".join(contents)
f.write(contents)
f.close()
replace_score("file_path", 10, "replacing_text")
This is Tim Osadchiy's code:
def replace_score(file_name, line_num, text):
f = open(file_name, 'r')
contents = f.readlines()
f.close()
contents[line_num] = text+"\n"
f = open(file_name, "w")
contents = "".join(contents)
f.write(contents)
f.close()
replace_score("file_path", 10, "replacing_text")
This code does work but just remember that the line_num will always be one above the actual line number (as it is an index). So if you wanted line 9 then enter 8, not 9. Also, do not forget to put .txt at the end of the file path (I would've commented but do not have a high enough reputation)

Categories

Resources