Writing new rows into CSV - python-3.x

Im not a dedicated programmer and its my first time doing a thing like this.
I made a While loop which uses entries that would be written into a CSV file.
I dont know how to repeat the loop so new values would be written into the new rows in alphabetical order.
I managed to make this program that works, but only has a one time entry into a one single row. Every time you would restart the program and enter something new it would override the old data row in CSV.
import csv
fields = ['Name', 'Surname', 'Status']
rows = [[]]
while True:
status=input("Enter status number: ")
if status !="3":
print("Wrong status number.")
else:
surname=input("Enter surname: ")
name=input("Enter name: ")
value=surname+"-"+name+"-"+name+"."+surname+"#mail.com"+","+status
print(value)
value=name+","+surname+","+name+"."+surname+"#mail.com"+","+status
for inner_row in rows:
_name=name
_surname=surname
_name_surname=name+"."+surname+"#mail.com"
rows[0].append(_name)
rows[0].append(_surname)
rows[0].append(_name_surname)
rows[0].append(status)
break
filename = "university_records.csv"
with open(filename, 'w') as csvfile:
csvwriter = csv.writer(csvfile)
csvwriter.writerow(fields)
csvwriter.writerows(rows)

To not overwrite the data everytime you run the program, you can simply change the w to an a in the with-context manager:
with open(filename, "a") as csvfile:
The "w" is for write, the "a" is for append
Howver, you are writing the fields (name, surname etc) everytime you run the program as well, this you can fix with a simple if-statement. the file-object (csvfile) has a method called tell() which returns the position of the cursor in the file-object. If the position is 0, the file is new and you print the fields. Else you skip it
if csvfile.tell() == 0:
csvwriter.writerow(fields)
I also think you are missing a field for the file to be a correct csv-file.
fields = ['Name', 'Surname', 'email', 'Status']
Hope this helped

import csv
import os
fields = ['Name', 'Surname', 'Email', 'Status']
filename = "university_records.csv"
rows = []
if os.path.isfile(filename):
with open(filename) as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader) # skip header
for row in csv_reader:
rows.append(row)
while True:
status = input("Enter status number (or 'exit' to exit): ")
if status == "exit":
break
if status != "3":
print("Wrong status number.")
else:
surname = input("Enter surname: ")
name = input("Enter name: ")
email = name + "." + surname + "#mail.com"
rows.append([name, surname, email, status])
with open(filename, 'w') as csv_file:
csv_writer = csv.writer(csv_file)
csv_writer.writerow(fields)
csv_writer.writerows(sorted(rows))

Thanks for the help guys. I had this assignment so I didn't want to 100% "cheat" as copy pasting your code. So I mixed a bit of both, up to the point where I could explain what is happening in the code.
Best regards!

Related

When editing data in a CSV how do you exclude/only include certain columns?

I've got a CSV of client details for a bank project in Python 3. I've managed to create a function in which you can edit the client details but I want to exclude the last 2 columns as and and can't figure out how.
Example of CSV data:
first_name,last_name,title,pronouns,dob,occupation,account_balance,overdraft_limit
Garner,Coupman,Ms,Male,14/04/2022,General Manager,2200.76,2.28
Jens,Eldrid,Honorable,Male,13/11/2021,Research Associate,967.64,79.15
Edit function:
if choice == "4":
editClient = int(input("Please enter the index number of the client you wish to edit: "))
print("Please enter the details for each of the following: ")
for i in range(len(existing_clients[0])):
newDetails = input("Enter new data for " + str(existing_clients[0][i]) + ": ")
existing_clients[editClient][i] = newDetails
changes = input("Are you sure you'd like to make these changes? Enter Yes or No")
if changes == ("Yes"):
# Newline fixed the spacing issue I was having
with open("mock_data.csv", "w+", newline="") as file:
reader = csv.writer(file)
for i in range(len(existing_clients)):
reader.writerow(existing_clients[i])
if changes == ("No"):
exit()
I've tried changing
for i in range(len(existing_clients[0])):
to
for i in range(len(existing_clients[0:6])):
and I thought this worked until I tried editing a client later the row 6.
I've also messed around a lot with
newDetails = input("Enter new data for " + str(existing_clients[0][i]) + ": ")
to no avail.
Edit the row with slicing and exclude the last two columns:
with open("mock_data.csv", "w", newline="") as file:
writer = csv.writer(file)
for client in existing_clients:
writer.writerow(client[:-2]) # exclude last two columns
Working example with data:
input.csv
first_name,last_name,title,pronouns,dob,occupation,account_balance,overdraft_limit
Garner,Coupman,Ms,Male,14/04/2022,General Manager,2200.76,2.28
Jens,Eldrid,Honorable,Male,13/11/2021,Research Associate,967.64,79.15
test.py
import csv
with open('input.csv', newline='') as f:
reader = csv.reader(f)
data = list(reader)
with open('output.csv', 'w', newline='') as f:
writer = csv.writer(f)
for line in data:
writer.writerow(line[:-2])
output.csv
first_name,last_name,title,pronouns,dob,occupation
Garner,Coupman,Ms,Male,14/04/2022,General Manager
Jens,Eldrid,Honorable,Male,13/11/2021,Research Associate
To select specific columns, you could concatenate different slices:
writer.writerow(line[:2] + line[5:6]) # column indexes 0, 1, and 5
Or use DictReader/DictWriter:
import csv
with open('input.csv', newline='') as f:
reader = csv.DictReader(f)
data = list(reader)
with open('output.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['last_name', 'occupation'], extrasaction='ignore')
writer.writeheader()
for line in data:
writer.writerow(line)
output.csv
last_name,occupation
Coupman,General Manager
Eldrid,Research Associate

How to add a text after certain text found in a file in python?

I want to make a switch case.If option 1 is pressed then some info is added to a csv file and after exit the case if again run the code and choose option 2 then it search some text in file and if found then add something to it.
I have tried the code given below.It runs option 1 correct but give errors in option 2.
from datetime import datetime
import fileinput
today = datetime.now()
In = str(today.strftime("%d/%m/%Y , %H:%M:%S"))
In1=In.rpartition(' , ')[0]
today = datetime.now()
Out = str(today.strftime("%d/%m/%Y , %H:%M:%S"))
out1=Out.rpartition(' , ')[2]
name=input("enter name of employee: ")
attend1=name+" , "+In1
f = open("Attend.csv", "a")
filename="Attend.csv"
while True:
print("1. Enter In Time\n2. Enter Out Time")
choice=input("Enter your choice: ")
if choice == "1":
attend = name+" , "+In
print(attend)
f.write(attend+"\n")
elif choice == "2":
attend = name+" , "+Out
print(attend)
f = open("Attend.csv", "r+")
for lines in f:
if attend1 in lines:
lines=lines.replace(lines,lines+" , "+out1)
f.write(lines+"\n")
else:
print("Please choose the correct entry.")
break
f.close()
The first case is easy, since it is just adding a line to the end of file. The second case is not working because you are just adding the time at the end, without strip the line and not searching for your line to be modified.
There is a problem in case the out time was added in the same iteration as the in, that means the file modification is not visible until you close the file, so you wouldn't find the in register.
By using this answer on how to search and replace a line in a file I came up with this:
from datetime import datetime
from os import fdopen, remove
from tempfile import mkstemp
from shutil import move
def end_employee_day(filename, employee, end_time):
updated = False
#Create temp file
temp, abs_path = mkstemp()
with fdopen(temp,'w') as new_file:
with open(filename) as old_file:
for line in old_file:
# Search for employee in register
if line.startswith(employee) and len(line.split(" , ")) == 3:
if updated:
print(f"Multiple in register found for {employee}")
updated = True
line = f"{line.strip()} , {end_time}\n"
print(line)
new_file.write(line)
#Remove original file
remove(filename)
#Move new file
move(abs_path, filename)
if not updated:
print(f"In register not found for {employee}")
filename = "Attend.csv"
today = datetime.now
while True:
print("1. Enter In Time\n2. Enter Out Time")
choice = input("Enter your choice: ")
if choice not in ("1", "2"):
print("Quitting")
break
name = input("enter name of employee: ")
if choice == "1":
with open(filename, "a") as f:
now_time = str(today().strftime("%d/%m/%Y , %H:%M:%S"))
attend = f"{name} , {now_time}\n"
print(attend)
f.write(attend)
elif choice == "2":
now_time = str(today().strftime("%H:%M:%S"))
end_employee_day(filename, name, now_time)
This allows to add registers of multiple employees in the same run. I did this since it seemed a little weird for me to add the in and out times for the same employee at the same time.
This code does not keep you from entering multiple in registers of the same employee without having registered the out time. The out time will be added to all in registers it finds.
Hope it helps, do not hesiste if you have any questions.

How to add headers when creating csv file in python

I am getting "raw" data from a csv file, and putting only what I need for a new csv file that will be used to auto add users to a different system...
I am unsure how to add the correct headers needed for the file.
I've tried looking at other examples of adding headers but have not figured this out yet...
The headers I need to add are as follows:
"ID Card Number","Name","E-Mail","User Level","Position","Status","Covered Under Insurance","Paid Insurance"
(and in that order)
import csv
def studentscsv():
with open('..\StudentEmails_and_StudentNumbers.csv') as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
with open('mydirectory\student_users.csv', mode='w', newline='') as output_file:
write = csv.writer(output_file, delimiter=',', quoting=csv.QUOTE_MINIMAL)
for row in csv_reader:
a = row[0]
studentnumber = row[1]
firstname = row[2]
lastname = row[3]
grade = row[4]
studentname = firstname + " " + lastname
studentemail = firstname + "." + lastname + "#mydomain.org"
status = "Active"
position = "Student"
covered = "Yes"
paid = "Yes"
write.writerow([studentnumber, studentname, studentemail, grade, position, status, covered, paid])
def main():
"""
Controls the program execution
:param in_file: the name of the input file.
:return: None
"""
if __name__ == '__main__':
main()
The file generates fine with the way the code is written. I am just unsure what I need to change to add the headers.
Using the csv module, as you are, it's pretty straight forward. Define your headers in an array and then create a DictWriter with the fieldnames set to your array. Reference the following code and documentation:
import csv
with open('names.csv', 'w') as csvfile:
fieldnames = ['first_name', 'last_name']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})
writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'})
writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})
Here's the documentation:
https://docs.python.org/2/library/csv.html#csv.DictWriter

Saving list to a .csv file

I have made a code that opens a .csv file and takes a user input to filter it to a new list. What I am having trouble with is saving this new list to a .csv file properly.
This is my code:
#author: Joakim
from pprint import pprint
import csv
with open ('Change_in_Unemployment_2008-2014.csv') as csvfile:
readCSV = csv.reader(csvfile, delimiter=',')
next(readCSV) #Removing header
result = []
found = False
user_input = input("Please enter a full/partial NUTS code to filter by: ")
for row in readCSV:
if row[0].startswith(user_input):
result.append(row)
found = True
if found == False:
print("There are no registered NUTS codes containing your input.. Please try again")
if found == True:
print("\n Successfully found ", len(result), "entries!""\n")
pprint (result)
#store data in a new csv file
Stored_path = "C:\data_STORED.csv"
file = open(Stored_path, 'w')
writer = csv.writer(file)
writer.writerow(["NUTS CODE", " Municipality", " value"])
for i in range(len(result)):
new_row = result[i]
NUTS_CODE = new_row[0]
Municipality = new_row[1]
Value = new_row[2]
writer.writerow([NUTS_CODE, Municipality])
csvfile.close()
If one runs my code with an input of : PL, one gets this list:
[['PL11', 'odzkie', '2.2'],
['PL12', 'Mazowieckie', '1.2'],
['PL21', 'Maopolskie', '2.9'],
['PL22', 'Slaskie', '2'],
['PL31', 'Lubelskie', '1.1'],
['PL32', 'Podkarpackie', '5.8'],
['PL33', 'Swietokrzyskie', '2.6'],
['PL34', 'Podlaskie', '2.7'],
['PL41', 'Wielkopolskie', '1.6'],
['PL42', 'Zachodniopomorskie', '-1.1'],
['PL43', 'Lubuskie', '1.8'],
['PL51', 'Dolnoslaskie', '0'],
['PL52', 'Opolskie', '1.3'],
['PL61', 'Kujawsko-Pomorskie', '1.6'],
['PL62', 'Warminsko-Mazurskie', '2.4'],
['PL63', 'Pomorskie', '3.1']]'
Now I would like to store this neatly into a new .csv file, but when I use the code above, I only get a couple of values repeated throughout.
What is my error?

how do i add to a csv file from a different function in python

Am fairly new to programming and am needing a way to add input data from one function and have it add into a csv file
def songlists():
with open('songs.csv') as csvfile:
songs = csv.reader(csvfile, delimiter = ',')
x = [row for row in songs]
return x
def menu(x):
print("Songs to Learn 1.0 - ")
songlists()
print(len(x), "songs in list")
print("""Menu :
L - List songs
A - Add new song
C - Complete a song
Q - Quit""")
menuChoice = str(input('>>>'))
while menuChoice != "q":
if menuChoice == "l":
songlists()
i = 0
for row in x:
name, artist, year, learnt = row
print(str(i),'.', learnt, name, artist, "(", year, ")")
i += 1
elif menuChoice == "a":
songlists()
#want to be able to add to the csv file from here and be able to add the new name artists and year etc
#print("??")
elif menuChoice == "c":
print("???")
else:
print("Invalid choice, Choose again")
print("""Menu :
L - List songs
A - Add new song
C - Complete a song
Q - Quit""")
menuChoice = str(input('>>>'))
what i would like to do is on the input of "a" by the user in function menu() it prompts them to add the name and artist etc and then add it to the csv file which is opened in the songlist function.
sorry if this question is badly formatted.
thanks
I'm unsure as to the specifics of csv.reader but using the standard open("text.csv") you'd need to add the parameter 'a' (i.e. open(text.csv, 'a').write(new_song, ",", something_else, "\n") so as to open it in append mode, instead of the default read (or explicitly 'r') mode. Be careful not to use 'w' for write as this will wipe the file clean before writing.
I wrote a small piece of code that should help you to solve you problem. This is not perfect because I would use a class instead of returning 3 parameters but I think it is a good start and we can improve it later:
import csv
def getSong():
name = raw_input("Artist's name: ")
song = raw_input("Song's name: ")
year = raw_input("Year: ")
return name, song, year
def save(filename, name, song, year):
with open(filename, 'a') as csvfile:
writer = csv.writer(csvfile, delimiter=';')
writer.writerow([name, song, year])
(name, song, year) = getSong()
save("output.csv", name, song, year)
HTH

Resources