I'm trying to edit a single row in a csv file. I've got a CSV file that looks like the bellow:
TYPE|FOOD TYPE|FEED TIME|WASH TIME
LION|MEAT|4H|1D
FOX|MEAT|5H|3D
HEN|SEED|6H|6D
FISH|PLANTS|7H|99D
I want to edit the row based on its TYPE. If the user wants to edit the FOX row they only need to type FOX when prompted. The issue I'm facing is that the I can't edit the file for some reason.
My code is bellow, I open the existing db, find the row in question, change it, then write it, along with the other rows, into a temp file that I can overwrite the original with.
def edit_animal_entry(type):
with open(animal_csv, 'r') as file_read:
reader = csv.reader(file_read, delimiter="|")
with open(temp, 'w') as file_write:
writer = csv.writer(file_write)
for row in reader:
print(f"{' | '.join(row)}")
if row[0] == type:
animal_type, animal_food, animal_feed, animal_wash = animal_inputs()
writer.writerow([animal_type, animal_food, (animal_feed+"H"), (animal_wash+"D")])
else:
writer.writerow(row)
shutil.move(temp, animal_csv)
You've 'closed' the read file by stopping the with block before reading anything out of it. Therefore you aren't looping over your input file. A solution would be to open the input and the output file in the same with statement:
def edit_animal_entry(type):
with open(animal_csv, 'r') as file_read, open(temp, 'w') as file_write:
reader = csv.reader(file_read, delimiter="|")
writer = csv.writer(file_write)
for row in reader:
print(f"{' | '.join(row)}")
if row[0] == type:
animal_type, animal_food, animal_feed, animal_wash = animal_inputs()
writer.writerow([animal_type, animal_food, (animal_feed+"H"), (animal_wash+"D")])
else:
writer.writerow(row)
shutil.move(temp, animal_csv)
Related
everytime i run my code it overwrites to first line of output.txt.
How can i make it so it writes to a new line every time?
def calculate_averages(input_file_name, output_file_name):
with open(input_file_name) as f:
reader = csv.reader(f)
for row in reader:
name = row[0]
these_grades = list()
for grade in row[1:]:
these_grades.append(int(grade))
with open(output_file_name, 'w') as external_file:
print(name, mean(these_grades), end='\n', file=external_file)
external_file.close()
This is happening because you are reopening your file in "w" mode for each row, which will overwrite your file. You can open the file outside of the for loop to avoid this behaviour:
import numpy as np
import csv
def calculate_averages(input_file_name, output_file_name):
with open(input_file_name) as f:
reader = csv.reader(f)
with open(output_file_name, 'w') as external_file:
for row in reader:
name = row[0]
mean_of_grades = np.mean([int(x) for x in row[1:]])
external_file.write(f"{name} {mean_of_grades}\n")
You can use a different mode for this:
Instead of with open(output_file_name, "w") as external_file:,
Use with open(output_file_name, "a") as external_file.
"a" stands for append, which will append the text to the end of the file.
I hope I understood your question right.
I have a .txt file that is being written to by a python script.
Adam,3,2,4
Sorin,3,2,4
Sorin,0,0,0
new_record = studentName+","+str(Score1) +","+str(Score2) +","+str(Score3)
student_class = 0
while student_class != 1 or student_class != 2 or student_class != 3:
student_class=input("What class are you in?(1/2/3): ")
if student_class == "1":
file=open("Class1.txt", "a+")
file.write(new_record)
file.write("\n")
file.close()
with open("Class1.txt", 'r') as fp:
for count, line in enumerate(fp):
pass
break
I want the scores to be overwritten if the student name is the same. For example if I run the script again, and Sorin gets a score of "3,3,3" the .txt file would look like this:
Adam,3,2,4
Sorin,3,2,4
Sorin,0,0,0
Sorin 3,3,3
However I want it to turn out like this:
Adam,3,2,4
Sorin 3,3,3
There are some things missing in your code, like how we know which student we are working on, etc.
But either way, this is the approach I would take if the files you are working on are not too big, as the file contents will be stored in memory while editing.
It uses a StringIO as intermediary location where the rows are appended, except if the name matches the current student, and then the content of the StringIO as put in place of the original file.
Starting with:
Adam,3,2,4
Sorin,3,2,4
Sorin,0,0,0
And running the following
import csv
from io import StringIO
current_student = "Sorin"
current_scores = (3, 3, 3)
# obtain a temporary file-like object in memory with a csv writer
with StringIO() as f_tmp:
writer = csv.writer(f_tmp)
# open the input file for reading with a csv reader
with open("/tmp/classes.csv", "r", newline="") as f_in:
reader = csv.reader(f_in)
for row in reader:
# skip the rows of current_student
if row[0] == current_student:
continue
writer.writerow(row)
# add current_student and their scores
writer.writerow((current_student,) + current_scores)
# open the input file for writing
with open("/tmp/classes.csv", "w") as f_out:
f_out.write(f_tmp.getvalue())
You get
Adam,3,2,4
Sorin,3,3,3
I want to create a program which generates numbers from 0 to 100000 and stores it in a file then, remove the numbers i give as input
I have done the code for generating the numbers and storing them in a csv file
import csv
nums = list(range(0,100000))
with open('codes.csv', 'w') as f:
writer = csv.writer(f)
for val in nums:
writer.writerow([val])
and i tried to delete the row i wanted with this
import csv
import os
lines = list()
while True:
members= input("Please enter a number to be deleted: ")
with open('codes.csv', 'r') as readFile:
reader = csv.reader(readFile)
for row in reader:
lines.append(row)
for field in row:
if field == members:
lines.remove(row)
os.remove('codes.csv')
with open('codes.csv', 'a+') as writeFile:
writer = csv.writer(writeFile)
writer.writerows(lines)
but the file size is multiplying each time i remove a number, please help
Add check before appending to your list, something like this should work:
with open('codes.csv', 'r') as readFile:
reader = csv.reader(readFile)
for row in reader:
if all(field != members for field in row):
lines.append(row)
Ps: don't forget to clear lines by adding lines = [] at the beginning of the while loop (I assume you know what you're doing).
There a two problems:
The lines list is never cleared. Whenever a number is entered, everything is written again to lines.
When writing, the file is opened with the a+ attributes, which means "append and update" file.
Try to recreate the list within the outer while loop and override the file contents by opening the file with attribute w, like this:
import csv
import os
while True:
members= input("Please enter a number to be deleted: ")
lines = list()
with open('codes.csv', 'r') as readFile:
reader = csv.reader(readFile)
for row in reader:
lines.append(row)
for field in row:
if field == members:
lines.remove(row)
os.remove('codes.csv')
with open('codes.csv', 'w') as writeFile:
writer = csv.writer(writeFile)
writer.writerows(lines)
I'm trying to make a program which stores a list of names in a CSV file, and I'm trying to add a function to delete rows, which isn't working as it deletes everything in the CSV file.
I've tried using writer.writerow(row), which hasn't worked.
memberName = input("Please enter a member's name to be deleted.")
imp = open('mycsv.csv' , 'rb')
out = open('mycsv.csv' , 'wb')
writer = csv.writer(out)
for row in csv.reader(imp):
if row == memberName:
writer.writerow(row)
imp.close()
out.close()
I expected the program to only delete rows which contained memberName, but it deletes every row in the CSV file.
How do I change it to only delete a single row?
You can't write to the same file while reading it. Instead, use another file for output, e.g.:
import csv
member_name = input("Please enter a member's name to be deleted: ")
with open('in_file.csv') as in_file, open('out_file.csv', 'w') as out_file:
reader = csv.reader(in_file)
writer = csv.writer(out_file)
for row in reader:
if member_name not in row: # exclude a specific row
writer.writerow(row)
Alternatively, you could store needed rows in memory and write them back to the input file after resetting the file pointer:
import csv
member_name = input("Please enter a member's name to be deleted: ")
with open('in_file.csv', 'r+') as in_file:
reader = csv.reader(in_file)
rows = [row for row in csv.reader(in_file) if member_name not in row]
in_file.seek(0)
in_file.truncate()
writer = csv.writer(in_file)
writer.writerows(rows)
This worked for me: you could write the contents of the csv file to a list, then edit the list in python, then write the list back to the csv file.
lines = list()
memberName = input("Please enter a member's name to be deleted.")
with open('mycsv.csv', 'r') as readFile:
reader = csv.reader(readFile)
for row in reader:
lines.append(row)
for field in row:
if field == memberName:
lines.remove(row)
with open('mycsv.csv', 'w') as writeFile:
writer = csv.writer(writeFile)
writer.writerows(lines)
I want to use the For Loop and print a row one by one whatever i required.
here is my code:
import csv
with open("details.csv") as csvFile:
reader = csv.DictReader(csvFile)
for row in reader:
if['age'] == '21':
print(row['Name'], row['age'], row['DOB'])
else:
continue
Here i want run the for loop until 6 times and also i want specific data of who ever age is '21', that person details only i want print, if it is other than '21' then skip the row. but my code is doesn't perform exactly like i want.
can anyone help me..?
Thank you :)
my csv is:
Name age dob
Arun 21 01/08/93
Banni 20 05/11/94
charan 23 23/03/92
nani 21 04/05/93
Simple error: Try this
import csv
with open("details.csv") as csvFile:
reader = csv.DictReader(csvFile)
for row in reader:
if row['age'].strip() == '21': #error in this line
print(row['Name'], row['age'], row['DOB'])
else:
continue
I tried your code and your file and got an error.
Then I replaced tabs in your csv file with commas and capitalized "dob" to "DOB":
Name,age,DOB
Arun,21,01/08/93
Banni,20,05/11/94
charan,23,23/03/92
nani,21,04/05/93
Then the output was correct:
>>>
Arun 21 01/08/93
nani 21 04/05/93
>>>
Of course I changed Line 5 to if row['age'] == '21':
By default DictReader uses comma , as a seperator between two fields but your csv file uses tabs.
If you don't want to change your csv file the solution is to change the creation of your DictReader to
reader = csv.DictReader(f, delimiter='\t')
Next change the line if['age'] == '21': to if row['age'] == '21':.
Finally row['DOB'] should be row['dob'] as the field names are case sensitive.
Try This if you dont have specified the header in csv file
import csv
import sys
f = open("File_Name.csv", 'rt') #open the file reading
print "Name\tAge\tDOB"
try:
reader = csv.reader(f)
for row in reader:
if row[1] == '21': #Check the condition
print "%s\t%s\t%s" %(row[0],row[1],row[2]) #print the columns
else:
continue
finally:
f.close() #close the file at the end
and if the file has header as first line(Name,Age,DOB) then use following
import csv #import csv package
with open("details.csv") as csvFile: #open the file
reader = csv.DictReader(csvFile)
for row in reader: #iterate the file
if row['age'].strip() == '21': #check the condition
print(row['Name'], row['age'], row['DOB'])
else: #skip if not satisfies the condition
continue