I am trying to make a contact book application with command-line arguments. This is the code written so far to update the new contact details of a particular contact. args.name has the name of the contact. And args.number has the new number which needs to be updated.
How can I update the entire line? When I run this, it replaces the entire file, contacts.txt, with an empty string. This functionality will also help in the delete function.
thefile = open("contacts.txt","w+")
lines = thefile.readlines()
for line in lines:
if name in line:
line.replace(line,"Name: "+ args.name + " Number: "+args.number+ "\n")
You could firstly read the data from the file, create an empty string, append each line to the newly created string conditionally, and write(replace) the newly obtained string onto the existing file.
f1 = open('contacts.txt','r')
data = f1.readlines()
f1.close()
new_data = ""
for line in data:
if name in line:
update = line.replace(line,"Name: "+ args.name + " Number: "+args.number+ "\n")
new_data += update
else:
new_data += line
f2 = open('contacts.txt','w')
f2.write(new_data)
f2.close()
When you open a file with "w+" python erase the file !
First you whoud write two function: One that writes data and the other read data
def reader():
f = open("MYFILE.txt", "r")
lines = f.readlines()
f.close()
return lines
def writer(data):
f = open("MYFILE.txt", "w")
for i in data:
f.write(i)
f.close()
Then you can actualise lines how you want:
lines = reader()
for i in range(len(lines)):
if lines[i] == "Something\n":
lines[i] = "New_Value\n"
writer(lines)
Related
I am looking to replace one text file with the contents of another if they are not the same.
Whenever I run this script, "['" and "']" are added on to the old_text.txt file, which means it will never match with new_text.txt file.
How do I remove these characters so the .txt files have the exact same contents after running this script?
old_text = open('old_text.txt', 'r+')
new_text = open('new_text.txt', 'r+')
old_text_compare = str(old_text.readlines())
new_text_compare = str(new_text.readlines())
if old_text_compare != new_text_compare:
print("difference")
old_text = open('old_text.txt', 'w')
old_text.write(str(new_text_compare))
else:
print("no difference")
If you want to compare file contents directly, use .read() rather than .readlines()
with open('old_text.txt', 'r+') as f1, open('new_text.txt', 'r+') as f2:
old = f1.read()
new = f2.read()
if old != new:
with open('new_text.txt', 'w') as f1:
f1.write(old)
else:
print("no difference")
You want to compare the list of lines directly, like so:
if old_text.readlines() != new_text.readlines():
...
I have a multiline string, which needs to be pasted and saved into a .txt file. I need also use some characters from the string as file name.
Here is an input example:
ABCD 0000/20/02
Q) abc/yxz/IV/A /000/999
A) XYZ B) 2008311600 C) 2009301559
E) texttexttext
texttext
File name should contain 6 numbers after B) : 200831 and the extension txt.
That's what I have:
print ('Paste new NOTAM starting with AXXXX/20: ') ##paste notam
lines = []
while True:
line = input()
if line:
lines.append(line)
else:
break
file_name= line[line.find("B) ")[6]:]
print (file_name)
with open(input(file_name + '.txt', "w+")) as f:
for line in lines:
f.write(line)
f.write('\n')
You could use regex to find out file name:
import re
string = '''ABCD 0000/20/02<br />
Q) abc/yxz/IV/A /000/999<br />
A) XYZ B) 2008311600 C) 2009301559<br />
E) texttexttext<br />
texttext<br />'''
filename = re.findall('B\) (\d\d\d\d\d\d\d)', string)[0]
with open(f'{filename}.txt', 'w') as f:
f.write(string)
Output file is 2008311.txt
so here i'm pasting my input, which is multiline string:
print ('Paste new NOTAM starting with AXXXX/20: ') ##paste notam
lines = []
while True:
line = input()
if line:
lines.append(line)
else:
break
Now i need to simply use those 6 characters from already pasted input in file name
In your code, all lines need to be checked, not only one line, so:
for line in lines:
if "B)" in line:
file_name = line[line.find("B) ")[6]:]
print (file_name)
Then, it is not really clear from your question whether you keep all multiline strings in memory or in separate files. Either way, you can write a function so that you can use it in different scenarios:
def parse_lines(lines):
for line in lines:
if "B)" in line:
file_name = line[line.find("B) ")[6]:]
print (file_name)
with open(file_name + '.txt', "w+") as f:
for line in lines:
f.write(line)
f.write('\n')
So your code will look like this:
print ('Paste new NOTAM starting with AXXXX/20: ') ##paste notam
lines = []
while True:
line = input()
if line:
lines.append(line)
else:
break
parse_lines(lines):
Or if you plan to parse batch files with this method:
import sys
with open(sys.argv[0], 'r') as f:
lines = f.readlines()
parse_lines(lines)
I have a text file with names and results. If the name already exists, only the result should be updated. I tried with this code and many others, but without success.
The content of the text file looks like this:
Ann, 200
Buddy, 10
Mark, 180
Luis, 100
PS: I started 2 weeks ago, so don't judge my bad code.
from os import rename
def updatescore(username, score):
file = open("mynewscores.txt", "r")
new_file = open("mynewscores2.txt", "w")
for line in file:
if username in line:
splitted = line.split(",")
splitted[1] = score
joined = "".join(splitted)
new_file.write(joined)
new_file.write(line)
file.close()
new_file.close()
maks = updatescore("Buddy", "200")
print(maks)
I would suggest reading the csv in as a dictionary and just update the one value.
import csv
d = {}
with open('test.txt', newline='') as f:
reader = csv.reader(f)
for row in reader:
key,value = row
d[key] = value
d['Buddy'] = 200
with open('test2.txt','w', newline='') as f:
writer = csv.writer(f)
for key, value in d.items():
writer.writerow([key,value])
So what needed to be different mostly is that when in your for loop you said to put line in the new text file, but it's never said to Not do that when wanting to replace a score, all that was needed was an else statement below the if statement:
from os import rename
def updatescore(username, score):
file = open("mynewscores.txt", "r")
new_file = open("mynewscores2.txt", "w")
for line in file:
if username in line:
splitted = line.split(",")
splitted[1] = score
print (splitted)
joined = ", ".join(splitted)
print(joined)
new_file.write(joined+'\n')
else:
new_file.write(line)
file.close()
new_file.close()
maks = updatescore("Buddy", "200")
print(maks)
You can try this, add the username if it doesn't exist, else update it.
def updatescore(username, score):
with open("mynewscores.txt", "r+") as file:
line = file.readline()
while line:
if username in line:
file.seek(file.tell() - len(line))
file.write(f"{username}, {score}")
return
line = file.readline()
file.write(f"\n{username}, {score}")
maks = updatescore("Buddy", "300")
maks = updatescore("Mario", "50")
You have new_file.write(joined) inside the if block, which is good, but you also have new_file.write(line) outside the if block.
Outside the if block, it's putting both the original and fixed lines into the file, and since you're using write() instead of writelines() both versions get put on the same line: there's no \n newline character.
You also want to add the comma: joined = ','.join(splitted) since you took the commas out when you used line.split(',')
I got the result you seem to be expecting when I put in both these fixes.
Next time you should include what you are expecting for output and what you're giving as input. It might be helpful if you also include what Error or result you actually got.
Welcome to Python BTW
Removed issues from your code:
def updatescore(username, score):
file = open("mynewscores.txt", "r")
new_file = open("mynewscores2.txt", "w")
for line in file.readlines():
splitted = line.split(",")
if username == splitted[0].strip():
splitted[1] = str(score)
joined = ",".join(splitted)
new_file.write(joined)
else:
new_file.write(line)
file.close()
new_file.close()
I believe this is the simplest/most straightforward way of doing things.
Code:
import csv
def update_score(name: str, score: int) -> None:
with open('../resources/name_data.csv', newline='') as file_obj:
reader = csv.reader(file_obj)
data_dict = dict(curr_row for curr_row in reader)
data_dict[name] = score
with open('../out/name_data_out.csv', 'w', newline='') as file_obj:
writer = csv.writer(file_obj)
writer.writerows(data_dict.items())
update_score('Buddy', 200)
Input file:
Ann,200
Buddy,10
Mark,180
Luis,100
Output file:
Ann,200
Buddy,200
Mark,180
Luis,100
I'm new to python and I'm trying various small things to see how they work:
items = dict()
with open(path) as f:
content = f.readlines()
for line in content:
splitStuff = line.split('!')
if splitStuff[0] in item:
items[splitStuff[0]] += ',' + Results[1]
else:
items[splitStuff[0]] = Results[1]
f.close()
with open(path2, 'a') as f:
for key, value in items.items():
f.write(key + '!' + value)
f.close()
It opens a file with this content:
3!Angel
3!Devil
4!Nasko
4!Pesho
4!Gosho
5!Kalin
6!Gancho
6!Boncho
6!Toncho
6!Moncho
And ends up writing a file with this content:
3!Angel
,Devil
4!Nasko
,Pesho
,Gosho
5!Kalin
6!Gancho
,Boncho
,Toncho
,Moncho
The part I don't understand is where are those new lines appearing from every time I edit a value?
EDIT: This is the desired output.
3!Angel,Devil
4!Nasko,Pesho,Gosho
5!Kalin
6!Gancho,Boncho,Toncho,Moncho
EDIT2: Never mind figured it out. Its because there are new lines in the original file and apparently reading file line by line catches them as well in python, unlike c# where they are ignored.
Lines you read with readlines() have a trailing newline.
for line in content:
line = line.rstrip()
splitStuff = line.split('!')
... etc ...
A solution could look like this:
path = "file1"
path2 = "file2"
items = dict()
with open(path) as f:
content = f.readlines()
for line in content:
splitStuff = line.split('!')
if splitStuff[0] in items:
items[splitStuff[0]] += ',' + splitStuff[1][:-1]
else:
items[splitStuff[0]] = splitStuff[1][:-1]
f.close()
with open(path2, 'a') as f:
for key, value in items.items():
f.write(key + '!' + value)
f.write("\n")
f.close()
You just had to remove the newline from each line of the file by adding [:-1].
I am trying to add a permanent header for a text file and along with the headers there should be the corresponding information i.e:
My code snippet:
name = input ("Name: ")
age = input("Age: ")
BirthYear = input("Birth Year: ")
file = open ("info.txt", "a")
file.write ("Name Age Grade\n")
file.write ("{} / {} / {}\n".format(name, age, birthYear))
file.close()
So far the code just outputs the following into a text file :
Name Age BirthYear
name / 16 / 1999
the header is not permanently on the top of the page. The corresponding information of each header should align to the headers;
I would like it to look something like the following:
Name Age BirthYear
Sam 22 1993
Bob 21 1992
it has to be in a text file.
What about just opening the file and writing in the header and then using a new with block to loop through and write in the individual records? I came across your question as I also needed to print a header into my csv text file. Eventually I just did the following (using your example):
header = "Name, Age, BirthYear"
with open('results.txt', 'a') as f:
f.write(header + "\n")
f.close
with open('results.txt', 'a') as f:
for x in rows_sub:
f.write(str(x) + ", " + c + "\n") #the line I needed to have printed via a loop
text files do not have a header. If you want a true header, you'll need a more complex format. Alternatively, if you just need something that acts like a header, then you need to figure out how many characters fit on your page vertically, and print the header every N lines.
For horizontal alignment, make use of the extra tokens you can use with format(). As an example:
>>> print('{a:^8}{b:^8}{c:^8}'.format(a='this', b='that', c='other'))
this that other
where ^8 says I want the string centered across 8 characters. Obviously you have to choose (or derive) the value that works for your data.
Check to see if the header row already exists, write it in to the file if it doesn't exist in the first line.
name = input ("Name: ")
age = input("Age: ")
BirthYear = input("Birth Year: ")
filename = "info.txt"
header = "Name Age Grade\n"
def WriteHeader(filename, header):
"""
;param filename: a file path
;param header: a string representing the file's "header" row
This function will check if the header exists in the first line
and inserts the header if it doesn't exist
"""
file = open(filename, 'r')
lines = [line for line in file]
file.close()
if lines and lines[0] == header:
# There are some lines in the file, and first line is the header
return True
else:
# The first line is NOT the header
file = open(filename, w)
# Rewrite the file: append header if needed, and all lines which previously were there
# excluding any misplaced header lines which were not at row 1
file.write(header + ''.join([line for line in lines if not line == header]))
file.close()
return True
if __name__ == '__main__':
if WriteHeader(filename, header):
file = open(filename, 'a')
file.write("{} / {} / {}\n".format(name, age, BirthYear))
file.close()
else:
print 'there was some problems...'
On second thought, this is simpler:
def WriteHeader2(filename, header):
# Always writes the header.
file = open(filename, 'r')
# remove any matching 'header' from the file, in case ther are duplicate header rows in the wrong places
lines = [line for line in file if not line == header]
file.close()
# rewrite the file, appending the header to row 1
file = open(filename, w)
file.write(''.join([line for line in lines].insert(0,header))
file.close()