I am beginning to learn python and I have this project where I have a menu that either adds, lists, or updates values for books in a csv. The headers are "BookName", "AuthorName", "SharedWith", "IsRead" and I am trying to change the "IsRead" row for a given book added by the user.
My problem is that whenever I am trying to edit the row that contains that book, I end up deleting all other rows instead. All I want to do is to update a value for a certain row in a csv. Here's the function that I wrote.
def updateBook():
book_name = input("Enter book name: ")
import csv
rows_list = []
with open('booksDB.csv', mode='r') as file:
rows = list(csv.DictReader(file, fieldnames=("BookName", "AuthorName", "SharedWith", "IsRead")))
for row in rows:
rows_list.append(row["BookName"]) # we store every book name in a list
if book_name not in rows_list: # we search the book the user typed in our list
add_new_book = input(f' The {book_name} book does not exits. Would you like to add it? (Y/N)? ')
if add_new_book.upper() == "N":
return
else:
addBook()
return
else:
book_read = input("Is the book read? (Y/N)? ")
if book_read.upper() == 'Y':
book_read = True
else:
book_read = False
rows = []
with open('booksDB.csv', mode='r') as file:
rows = list(csv.DictReader(file, fieldnames=("BookName", "AuthorName", "SharedWith", "IsRead")))
for row in rows:
if row["BookName"] == book_name:
row["IsRead"] = book_read
break
with open('booksDB.csv',mode='r+') as file: # WIP, here I can't make the csv keep all books in the list when editing a certain one
csv_writer = csv.DictWriter(file, fieldnames=[
"BookName", "AuthorName", "SharedWith", "IsRead"
])
if row["IsRead"] == book_read:
csv_writer.writerow({"BookName": row.get("BookName"),
"AuthorName": row.get("AuthorName"),
"SharedWith": row.get("SharedWith"),
"IsRead": book_read})
print("Book was updated successfully")
The First Thing You Should Open Your CSV File In a 'w' Mode Not 'r'
After I Looked at your Code You Didn't Respect The Indentation For your Function Try To Fix it First
Did You Try To Give Input First
roww = input("Enter The Name Of The Row Here : ")
and After use it :
for row in rows:
if row["BookName"] == book_name:
row[rf"{roww}"] = book_read
break
Try This it Might Help
Thank you guys for your support. I made a small tweak and managed to get the code working 100% with the following lines:
def updateBook():
book_name = input("Enter book name: ")
import csv
rows = []
rows_list = []
with open('booksDB.csv', mode='r') as file:
rows = list(csv.DictReader(file, fieldnames=("BookName", "AuthorName", "SharedWith", "IsRead")))
for row in rows:
rows_list.append(row["BookName"]) # we store every book name in a list
if book_name not in rows_list: # we search the book the user typed in our list
add_new_book = input(f' The {book_name} book does not exits. Would you like to add it? (Y/N)? ')
if add_new_book.upper() == "N":
return
else:
addBook()
return
else:
book_read = input("Is the book read? (Y/N)? ")
if book_read.upper() == 'Y':
book_read = True
else:
book_read = False
rows = []
with open('booksDB.csv', mode='r') as file:
rows = list(csv.DictReader(file, fieldnames=("BookName", "AuthorName", "SharedWith", "IsRead")))
for row in rows:
if row["BookName"] == book_name:
row["IsRead"] = book_read
break
with open('booksDB.csv',mode='w') as file:
csv_writer = csv.DictWriter(file, fieldnames=["BookName", "AuthorName", "SharedWith", "IsRead"])
csv_writer.writerows(rows)
print("Book was updated successfully!")
Related
I'm trying to end the code, but I have problem how to slice data frame based on user's input. Is there any option to do this without pandas?
def dataSet_read():
enter = input('Enter file path:')
csvreader = csv.reader(open(enter))
head_inp = input('Has the file headers? Select Y or N:\n').upper()
header = []
if head_inp == 'Y':
header = next(csvreader)
print('\nFile headers:\n\n', header)
elif head_inp == 'N':
print("'\nFile doesn't have headers")
else:
print('Incorrect selection!!!')
sys.exit()
with open(str(enter), "r") as csvfile:
reader_variable = csv.reader(csvfile, delimiter = ",")
rows_inp = input("\nPlease provide range which you'd like to see using ',', otherwise all dataframe will open all dataset.\n")
if rows_inp == '':
for row in reader_variable:
print(row)
else:
print("????")
cast it to list then you can slice like what it is in normal list structure.
enter = input('Enter file path:')
rows_inp = input("slice")
with open(enter , 'r') as f:
reader_variable = csv.reader(f)
reader_list= list(reader_variable)
for row in reader_list[:rows_inp]:#if you want slice the whole data
current_date = row[:rows_inp] #if you want slice per row
print(current_date)
I found the way to get what I need, maybe it's not the best approach but works :)
with open(str(enter), "r") as csvfile:
reader_variable = csv.reader(csvfile, delimiter = ",")
rows_inp = input("\nPlease provide range which you'd like to see using ',', otherwise all dataframe will open all dataset.\n")
if rows_inp == '':
for row in reader_variable:
print(row)
else:
i, j = rows_inp.split(',')
reader_list = list(reader_variable)
print(reader_list[int(i):int(j)+1])
I have three CSV files:
doctors.csv
1,John,Smith,Internal Med
2,Jone,Smith,Pediatrics
3,Jone,Carlos,Cardiology
patients.csv
1,Sara,Smith,20,07012345678,B1234
2,Mike,Jones,37,07555551234,L22AB
3,Daivd,Smith,15,07123456789,C1ABC
... and linked.csv, which I need to populate based on doctors.csv and patients.csv.
I'm taking two inputs from the user that correspond with the doctor ID and patient ID, and checking if they are present, and then writing them to the linked.csv file.
I'd like the linked.csv file to contain for each column:
[patientID,patientfirstname,patientsurname,doctorID,doctorfirstname,doctorlastname]
Unfortunately, I can't figure out how to read a specific row using the csv module and then extract the specific data I need from both files.
Here is the code I have so far:
#asking for input
print('Please select both a Patient ID and Doctor ID to link together')
patient_index = input('Please enter the patient ID: ')
doctorlink = input('Please select a doctor ID: ')
doctorpresent = False
patientpresent = False
# precence check for both values
with open('patiens.csv', 'r') as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
if patient_index == row[0]:
print('Patient is present')
patientpresent = True
with open('doctors.csv', 'r') as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
if patient_index == row[0]:
print('Doctor is present')
doctorpresent = True
if patientpresent == True and doctorpresent == True:
Here, I need to add the code necessary for extracting the rows.
I have used CSV library to read files from both files and combine them into a list.
import csv
# asking for input
print('Please select both a Patient ID and Doctor ID to link together')
patient_index = input('Please enter the patient ID: ')
doctor_index = input('Please select a doctor ID: ')
output = []
# opening the CSV file
with open('patient.csv', 'r') as f:
# reading the CSV file
reader = csv.reader(f, delimiter=',')
# iterating the rows
for row in reader:
if patient_index == row[0]:
output.append(row[0]) # appending patientID
output.append(row[1]) # appending patientfirstname
output.append(row[2]) # appending patientlastname
# opening the CSV file
with open('doctor.csv', 'r') as f:
# reading the CSV file
reader = csv.reader(f, delimiter=',')
# iterating the rows
for row in reader:
if doctor_index == row[0]:
output.append(row[0]) # appending doctorID
output.append(row[1]) # appending doctorfirstname
output.append(row[2]) # appending doctorlastname
print(output)
Output
['1', 'Sara', 'Smith', '1', 'John', 'Smith']
[patientID,patientfirstname,patientsurname,doctorID,doctorfirstname,doctorlastname]
Hope this helps. Happy Coding :)
This looks like a task better suited for a database, but here is a possible solution just using the csv module (pathlib here is just my preferred way to handle files):
import csv
from pathlib import Path
# Files
patients_csv = Path('patients.csv')
doctors_csv = Path('doctors.csv')
linked_csv = Path('linked.csv')
# Create in memory lists for patients and doctors
with patients_csv.open() as f:
reader = csv.reader(f)
patients = [_ for _ in reader]
with doctors_csv.open() as f:
reader = csv.reader(f)
doctors = [_ for _ in reader]
print('Please select both a Patient ID and Doctor ID to link together')
patient_id = input('Please enter the patient ID: ')
doctor_id = input('Please select a doctor ID: ')
# Is there a doctor that matches doctor_id?
doctor = [_ for _ in doctors if _[0] == doctor_id]
# Is there a patient that matches patient_id?
patient = [_ for _ in patients if _[0] == patient_id]
# Do we have a patient and a doctor match?
if patientt and doctor:
patient = patient[0]
doctor = doctor[0]
with linked_csv.open('a') as f:
print(*patient, *doctor, file=f, sep=',')
And here is the result of a test run of the code above, which is in app.py here:
$ ls
app.py doctors.csv patients.csv
$ cat doctors.csv
1,John,Smith,Internal Med
2,Jone,Smith,Pediatrics
3,Jone,Carlos,Cardiology
$ cat patients.csv
1,Sara,Smith,20,07012345678,B1234
2,Mike,Jones,37,07555551234,L22AB
3,Daivd,Smith,15,07123456789,C1ABC
$ python app.py
Please select both a Patient ID and Doctor ID to link together
Please enter the patient ID: 1
Please select a doctor ID: 1
$ cat linked.csv
1,Sara,Smith,20,07012345678,B1234,1,John,Smith,Internal Med
It can also be implemented independent of the csv module:
from pathlib import Path
# Files
patients_csv = Path('patients.csv')
doctors_csv = Path('doctors.csv')
linked_csv = Path('linked.csv')
# Create in memory lists for patients and doctors
with patients_csv.open() as f:
patients = [_.strip().split(',') for _ in f]
with doctors_csv.open() as f:
doctors = [_.strip().split(',') for _ in f]
print('Please select both a Patient ID and Doctor ID to link together')
patient_id = input('Please enter the patient ID: ')
doctor_id = input('Please select a doctor ID: ')
# Is there a doctor that matches doctor_id?
doctor = [_ for _ in doctors if _[0] == doctor_id]
# Is there a patient that matches patient_id?
patient = [_ for _ in patients if _[0] == patient_id]
# Do we have a patient and a doctor match?
if patientt and doctor:
patient = patient[0]
doctor = doctor[0]
with linked_csv.open('a') as f:
print(*patient, *doctor, file=f, sep=',')
Both examples are just starting points, which you can construct and improve above them.
I am extract the information from the csv file that the user inputs. For example if the user types in Nevada it will go through the csv file and pull the information from that row and print it to the user. But the result i keep getting is the last row in the csv file.
def create_csv(name):
with open('details.csv', 'rt') as f:
reader = csv.reader(f)
for row in reader:
if row[1] == name:
print(name)
return print(row)
page = requests.get("https://ix.cnn.io/data/novel-coronavirus-2019-ncov/us/states.json")
js_resp = json.loads(page.text)
states = []
case = []
deaths = []
for item in js_resp['data']:
states.append(item['name'])
case.append(item['cases'])
deaths.append(item['deaths'])
details = pd.DataFrame(
{'State': states,
'Cases': case,
'Death': deaths,
}
)
details.to_csv('details.csv')
select = int(input('Please enter how you would like to look up information '
'"Press 1 for State, 2 for City, 3 for Zip" '))
if select == 1:
# Get input of which state the user want to look up
s = input('Which state would you like to see ')
break
def false_to_true():
name = input("Input name: ")
file=open("users.txt","r")
lines = file.readlines()
file.close()
for line in lines:
username, lel, type = line.split("/")
while name == username:
name = input("input name again: ")
tip = True
with open("users.txt", "w") as users:
users.write(str(red))
#
#I do not know how to perform a given modification and enrollment into place in #the text.
#
#I wont to change word False to True for username i input.
#I have this text in file users:
#Marko123/male/False
#Mimi007/female/False
#John33/male/False
#Lisa12/female/False
#Inna23/female/False
#Alisa27/female/False
I won't to change word False to True for username I input.
I have this text in file users:
Marko123/male/False
Mimi007/female/False
John33/male/False
Lisa12/female/False
Inna23/female/False
Alisa27/female/False
You can just use the csv library and forget about string manipulation:
import csv
def false_to_true():
#read from user.txt file into list(data)
with open('users.txt', 'r') as userfile:
data = [row for row in csv.reader(userfile,
delimiter="/",
quoting=csv.QUOTE_NONE)]
while True:
#waiting for input until you enter nothing and hit return
username = input("input name: ")
if len(username) == 0:
break
#look for match in the data list
for row in data:
if username in row:
#change false to true
row[2] = True
#assuming each username is uniqe break out this for loop
break
#write all the changes back to user.txt
with open('users.txt', 'w', newline='\n') as userfile:
dataWriter = csv.writer(userfile,
delimiter="/",
quoting=csv.QUOTE_NONE)
for row in data:
dataWriter.writerow(row)
if __name__ == '__main__':
false_to_true()
Open the input and output files, make a set out of the user-input names (terminated by a blank line), then create a generator for strings of the proper format that check for membership in the user-input names, then write these lines to the output file:
with open('names.txt') as f, open('result.txt', 'w') as out:
names = {name for name in iter(input, '')}
f = ('{}/{}/{}'.format(a,b,'True\n' if a in names else c) for a,b,c in (line.split('/') for line in f))
output.writelines(f)
To modify a text file inplace, you could use fileinput module:
#!/usr/bin/env python3
import fileinput
username = input('Enter username: ').strip()
with fileinput.FileInput("users.txt", inplace=True, backup='.bak') as file:
for line in file:
if line.startswith(username + "/"):
line = line.replace("/False", "/True")
print(line, end='')
See How to search and replace text in a file using Python?
Ask for name and iterate throw your lines to check for username, like this:
def false_to_true():
name = input("Input name: ")
file=open("users.txt","r")
lines = file.readlines()
file.close()
users = open("users.txt", "w")
for line in lines:
username, lel, type = line.split("/")
if name == username:
type = 'True\n'# \n for new line type ends with '\n'
users.write("/".join([username, lel, type]))
users.close()
false_to_true()
I'm writing a python script that works with two csv files. Lets call them csv1.csv (original file to read) and csv2.csv (exact copy of csv1). The goal is to find the row and column in the csv file that corresponds to the the modified user-defined input.
csv format:(continues for about 2-3 thousand lines)
record LNLIM, ID_CO,OD_DV,ID_LN, ST_LN, ZST_LN, ID_LNLIM,LIMIT1_LNLIM, LIMIT2_LNLIM, LIMIT3_LNLIM
LNLIM, 'FPL', 'SOUT', '137TH_LEVEE_B', 'B', '137TH_AV', 'LEVEE', 'A', 1000, 1100, 1200
LNLIM, 'FPL', 'SOUT', '137TH_DAVIS_B', 'A', '137TH_AV', 'NEWTON', 'A', 1000, 1100, 1200
...
Let's say that the user is looking for 137TH_AV and NEWTON. I want to be able to go row by row and compare the two columns/row indices ST_LN and ZST_LN. If both columns match what the user inputted then I want to capture which row in the csv file that happened on, and use that information to edit the remaining columns LIMIT1_LNLIM LIMIT2_LNLIM LIMIT3_LNLIM on that row with new analog values.
I want to get the 3 new values provided by the user and edit a specific row, and a specific row element. Once I've found the place to replace the number values I want to overwrite csv2.csv with this edit.
Determining where the line segment is located in the array
import sys
import csv
import os
import shutil
LineSectionNames = []
ScadaNames = []
with open('Vulcan_Imp_Summary.csv', 'r') as file:
reader = csv.reader(file)
for row in reader:
LineSectionName = row[1]
ScadaName = row[29]
LineSectionNames.append(LineSectionName)
ScadaNames.append(ScadaName)
#Reformatting arrays for accurate references
LineSectionNames = [character.replace('\xa0', ' ') for character in LineSectionNames]
LineSectionNames = [character.replace('?', '-') for character in LineSectionNames]
ScadaNames = [character.replace('\xa0', ' ') for character in ScadaNames]
#Setting Line Section name as key and Scada name as value
ScadaDict = {}
for i in range(len(LineSectionNames)):
ScadaDict[LineSectionNames[i]] = ScadaNames[i]
#Prompt user for grammatical name of Line Section
print ('Enter the Line Section Name: (Example = Goulds-Princeton) \n')
user_input = input()
#Reference user input to dictionary value to convert input into SCADA format
def reformat():
print ('Searching for Line Section...' + user_input)
if user_input in ScadaDict:
value = ScadaDict[user_input]
print ('\n\t Match!\n')
else:
print ('The Line Section name you have entered was incorrect. Try again. \n Example = Goulds-Princeton')
reformat()
# Copying the exported file from Genesys
path = 'I://PSCO//DBGROUP//PatrickL//'
shutil.copyfile(path + 'lnlim_import.csv', path + 'lnlim_import_c.csv')
#Using the SCADA format to search through csv file
print ('Searching csv file for...' + user_input)
# Reading the copied file
record_lnlims = []
id_cos = []
id_dvs = []
id_lines = []
id_lns = []
st_lns = []
zst_lns = []
id_lnlims = []
limit1_lnlims = []
limit2_lnlims = []
limit3_lnlims = []
with open('lnlim_import_c.csv', 'r') as copy:
reader = csv.reader(copy)
for row in reader:
record_lnlim = row[0]
id_co = row[1]
id_dv = row[2]
id_line = row[3]
id_ln = row[4]
st_ln = row[5]
zst_ln = row[6]
id_lnlim = row[7]
limit1_lnlim = row[8]
limit2_lnlim = row[9]
limit3_lnlim = row[10]
record_lnlims.append(record_lnlim)
id_cos.append(id_co)
id_dvs.append(id_dv)
id_lines.append(id_line)
id_lns.append(id_ln)
st_lns.append(st_ln)
zst_lns.append(zst_ln)
id_lnlims.append(id_lnlim)
limit1_lnlims.append(limit1_lnlim)
limit2_lnlims.append(limit2_lnlim)
limit3_lnlims.append(limit3_lnlim)
#Reformatting the user input from GOULDS-PRINCETON to 'GOULDS' and 'PRINCETON'
input_split = user_input.split('-', 1)
st_ln1 = input_split[0]
zst_ln1 = input_split[1]
st_ln2 = st_ln1.upper()
zst_ln2 = zst_ln1.upper()
st_ln3 = "'" + str(st_ln2) + "'"
zst_ln3 = "'" + str(zst_ln2) + "'"
#Receiving analog values from user
print ('\n\t Found! \n')
print ('Enter the Specified Emergency Rating (A) for 110% for 7 minutes: ')
limit1_input = input()
print ('Enter the Specified Emergency Rating (A) for 120% for 7 minutes: ')
limit2_input = input()
print ('Enter the Specified Emergency Rating (A) for 130% for 5 minutes: ')
limit3_input = input()
Whenever I print the row_index it prints the initialized value of 0.
i = 0
row_index = 0
for i in range(len(st_lns)):
if st_ln3 == st_lns[i] and zst_ln3 == zst_lns[i]:
row_index = i
print(row_index)
limit1_input = limit1_lnlims[row_index]
limit2_input = limit2_lnlims[row_index]
limit3_input = limit3_lnlims[row_index]
csv_list = []
csv_list.append(record_lnlims)
csv_list.append(id_cos)
csv_list.append(id_dvs)
csv_list.append(id_lines)
csv_list.append(st_lns)
csv_list.append(zst_lns)
csv_list.append(id_lnlims)
csv_list.append(limit1_lnlims)
csv_list.append(limit2_lnlims)
csv_list.append(limit3_lnlims)
#Editing the csv file copy to implement new analog values
with open('lnlim_import_c.csv', 'w') as edit:
for x in zip(csv_list):
edit.write("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}\n".format(x))