I have a piece of code used to enter student information. But I want to transform it so that Admission no. cannot be repeated, when entering an existing number, a message will be printed if you want to re-enter an existing number. below is my code
import csv
student_fields = ['Admission no.','Name','Age','Email','Phone']
student_database = 'students.csv'
def add_student():
print("-------------------------")
print("Add Student Information")
print("-------------------------")
global student_fields
global student_database
student_data = []
for field in student_fields:
print(field)
value = input("Enter " + field + ": ")
student_data.append(value)
with open(student_database,"a",encoding = "utf-8") as f:
writer = csv.writer(f)
writer.writerows([student_data])
print("Data saved successfully")
input("Press any key to continue")
return
You can do something like this. As Barmar suggested, put the admission numbers in a set at the start of your definition. Then, check the user's input against those numbers. Create a while loop that doesn't let the user input any other value until they enter a new Admission no (and tell them that they are entering a duplicate admission number). Once everything looks good, write it to the csv.
import csv
student_fields = ['Admission no.','Name','Age','Email','Phone']
student_database = 'students.csv'
def add_student():
print("-------------------------")
print("Add Student Information")
print("-------------------------")
global student_fields
global student_database
# create a set of the already entered admission numbers
with open('students.csv', 'r') as file:
reader = csv.reader(file)
admissionNums = {x[0] for x in reader if x}
student_data = []
for field in student_fields:
print(field)
value = input("Enter " + field + ": ")
# while the user is entering the admission no. field and they are entering a duplicate, keep prompting them for a new/unique number
while field == 'Admission no.' and value in admissionNums:
print("Admission no. already in file, try again")
value = input("Enter " + field + ": ")
student_data.append(value)
# I also added `newline=''` so that it would stop creating an empty row when writing to the file
# You can remove this if you want to keep making a new row every time you write to it
with open(student_database,"a",encoding = "utf-8", newline='') as f:
writer = csv.writer(f)
writer.writerows([student_data])
print("Data saved successfully")
input("Press any key to continue")
# The return statement here is not necessary
Related
I am practicing python and doing an exercise where I have to ask for input of different information from patients of a hospital (name, last name, etc) this information has to be saved in a different json file. I managed to do it however I also have to make it so, with an input, I can remove/edit a specific patient from the dictionary (along with all of their info) while keeping the others intact.
I was thinking that maybe I could assign a number to every patient that's added, so this patient can be tracked with the number, however I'm not sure how to code that. I did however made a function to clear everything from the json file, but it has to remove/edit someone specific, not everyone.
My code so far is:
import json
def read_file(file_name):
obj_arch = open(file_name, 'rt', encoding='utf-8')
str_contenido = obj_arch.read()
res = json.loads(str_contenido)
obj_arch.close()
return res
def save_file(file_name, lista):
obj_arch = open(file_name, 'wt', encoding='utf-8')
str_content_to_save = json.dumps(lista)
print(str_content_to_save)
obj_arch.write(str_content_to_save)
obj_arch.close()
opcion = int(input("choose an option: 1 - read. 2 - save"))
if opcion == 1:
lista = read_file('prueba_json.json')
print("Full list:")
print(lista)
else:
lista = read_file('prueba_json.json')
while True:
print("--- PATIENT INFO ---")
Name = input("Input name: ")
Lastname = input("Input lastname: ")
DateB= input("Input date of birht: ")
repeat = input("Do you want to add more info?: ")
clean_file = input("Clean everything from the json file? (yes/no): ")
lista.append({
"Name": Name,
"Lastname": Lastname,
"Date of Birth": DateB
})
if repeat == 'no' or repeat == 'NO':
break
save_file('prueba_json.json',lista)
With this I was able to sabe the patients info in the json file, but how can I write another input like "Insert number of patient to remove or delete" to do that?
In order to clean the whole json file I've done it with this:
def clean_json():
with open('prueba_json.json', 'w') as arc:
arc.writelines(["[{}]"])
if clean_file == "yes" or clean_file == "YES":
clean_json()
Maybe I could adapt some of this to remove or delete someone instead of the whole file?
def main():
print("\nZIPCODE LOOKUP PROGRAM")
zlist,clist,slist=loadLists()
userInput = searchLoop(zlist,clist,slist)
def loadLists():
# create a list
try:
zlist = []
clist = []
slist = []
# open the file
zipFile = open("zipcodes.txt", "r")
for nextline in zipFile:
parsedlist = nextline.split(",")
zlist.append(parsedlist[0])
clist.append(parsedlist[1])
slist.append(parsedlist[2])
zipFile.close()
except IOError:
print("\nError - zipcodes.txt does not exist")
return zlist,clist,slist
def searchLoop(zlist,clist,slist):
# search the zip code the user entered
userInput = input("\nEnter a zip code to find (Press Enter key alone to stop): ")
while userInput != "":
if userInput in zlist:
where = zlist.index(userInput)
print("\n" + "\tThe city is " + city + "and the state is" + state + ".")
city = clist.index()
state = slist.index()
else:
print("\n" + "\tZipcode does not exist")
userInput = input("\nEnter a zip code to find (Press Enter key alone to stop): ")
return userInput
def findZipcode():
# find the zip code, city, and state
# what do I do about this
def printSearchResults():
#print the result
print("\n" + "\tThe city is " + city + "and the state is" + state + ".")
This is what it is suppose to look like
Enter a zip code to find (Press Enter key alone to stop): 90401
The city is SANTA MONICA and the state is CA.
You have parallel arrays (i.e., related information shares the same index within the arrays) containing the zip code, state and city, and you are given a zip code to retrieve information for.
The idea then would be to find the index of the item in zlist that matches the given zip code, and use that index to extract the city and state from the other two arrays.
For example (Python-looking pseudo-code):
define getInfo(zlist, clist, slist, zipcode):
for i = 0 to len(zlist) - 1 inclusive:
if zlist[i] = zipcode:
return clist[i] and slist[i]
return nothing and nothing
I cleaned up your code and I think the best approach is to use just a loop and a dictionary with keys to store the results, not lists.
def main():
"""Main function that triggers all other functions"""
print("\nZIPCODE LOOKUP PROGRAM")
my_list = load_lists()
search_loop(my_list)
def load_lists():
"""Open file, create a list with the data parsed as a list of dicts"""
my_list = []
with open("zipcodes.txt", "r") as zip_file:
for nextline in zip_file:
parsedlist = nextline.split(",")
my_list.append({"Zip":parsedlist[0], "City":parsedlist[1], "State":parsedlist[2]})
return my_list
def search_loop(my_list):
"""Search the zip code the user entered using a loop.
Then print that dictionary formatted for readability"""
user_input = input("\nEnter a zip code to find (Press Enter key alone to stop): ")
while user_input != "":
for item in my_list:
if str(user_input) == item['Zip']:
print(f"\n\tThe city is {item['City']} and the state is {item['State']}.")
break # No need to check other results since we found it
else:
print("\n\tZipcode does not exist")
userInput = input("\nEnter a zip code to find (Press Enter key alone to stop): ")
return
main() # Run the program
Result:
ZIPCODE LOOKUP PROGRAM
Enter a zip code to find (Press Enter key alone to stop): 1234
The city is TestCity and the state is Testing.
Enter a zip code to find (Press Enter key alone to stop): 4567
The city is MadeUpCity and the state is MadeUp.
Things to have in mind:
Use with to read files such as .txt, it will open and close them automatically and you'll avoid most of the errors that way. Read about it.
You can use docstrings (triple quoted string) as first things on what a function should do, to avoid the need of multiple comments everywhere.
And please don't use CamelCase in python except for classes. This
is explained in PEP8
f-strings makes prints prettier. f:"this is {city} and this is {state}." instead of "this is " + city + " and this is " + state + "."
I'm Creating a project in which i have two lists.
One list is user_ids where the user's usernames are stored.
Another is user_ratings where the user's ratings are stored.
At the corresponding index of username, user rating is stored.
If there's a new user, the list is appended dynamically at run-time.
Here's the code:
print("Welcome to Movie Predictor")
print("Enter your user id: ")
user_ids=["Vishnu"]
user_ratings=[3.5]
username=input()
print("Signing in...Please Wait!")
if username in user_ids:
user_index=user_ids.index(username)
avg_rating=user_ratings[user_index]
new_user=0
else:
user_ids.append(username)
user_ratings.append(3.5)
avg_rating=3.5
new_user=1
After my first run of the program, I have entered a username which is not there in the list and here are the arrays.
user_ids=["Vishnu","Power"]
user_ratings=["3.5","3.5"]
But here's the problem. The next time i run it again, My last element "Power" is getting replaced but a new item is not appended in the list.
Here's the list after 2nd run:
user_ids=["Vishnu","Ranger"]
user_ratings=["3.5","3.5"]
How to overcome this problem?
Try saving your data to disk after each run, and reading if back before next run:
import os.path
if not os.path.exists("mydatabase.txt"):
# initialize
user_ids=["Vishnu"]
user_ratings=[3.5]
else:
# read previous data from database file
user_ids=[]
user_ratings=[]
with open("mydatabase.txt", "r") as databasefile:
for line in databasefile:
userid, rating_str = line.split()
rating = float(rating_str)
user_ids.append(userid)
user_ratings.append(rating)
print("Welcome to Movie Predictor")
print("Enter your user id: ")
username=input()
print("Signing in...Please Wait!")
if username in user_ids:
user_index=user_ids.index(username)
avg_rating=user_ratings[user_index]
new_user=0
else:
user_ids.append(username)
user_ratings.append(3.5)
avg_rating=3.5
new_user=1
print("Current user ids: %s" % user_ids)
print("Current user ratings: %s" % user_ratings)
# write data to database file
with open("mydatabase.txt", "w") as databasefile:
for userid, rating in zip(user_ids, user_ratings):
databasefile.write("%s %.1f\n" % (userid, rating))
There is no loop here. You just overwrite the values each time.
try that:
A, B = [], []
while True:
A.append(3.5)
b = input('B value')
if b == '':
break
B.append(b)
print(A, B)
It is unclear which parts of the code you run again, but it seems that you are resetting your user ID and ratings lists in every run (3d and 4th line). Therefore "Powers" is not being replaced. Rather than that, a new list with Vishnu is created and your new input is added to it after the run.
You don't have a loop. The values in the list won't be saved between runs of the script
print("Welcome to Movie Predictor")
print("Enter your user id: ")
user_ids=["Vishnu"]
user_ratings=[3.5]
while True:
username=input()
print("Signing in...Please Wait!")
if username in user_ids:
user_index=user_ids.index(username)
avg_rating=user_ratings[user_index]
new_user=0
else:
user_ids.append(username)
user_ratings.append(3.5)
avg_rating=3.5
new_user=1
print("List of users: " + str(user_ids))
you probably want to use dicts and a while loop for input multiple users. This code keep iterating until user enters 'n' on the second input.
print("Welcome to Movie Predictor")
users = dict(Vishnu = 3.5)
a = 'y'
while a == 'y':
username=input("Enter your user id: ")
print("Signing in...Please Wait!")
if username in users:
print("do something if user exits")
else:
val = float(input(f"Enter value for {username}: "))
users[username] = val
print(users)
avg_rating = sum(users.values()) / len(users)
print(f"average rating: {avg_rating}")
a = ''
while a not in ['y','n']:
a = input("continue? (y/n)")
if a == 'n':
break
else:
continue
I am trying to create two programs one that writes the data to file golf.txt and the second which reads the records from golf.txt and displays them. The first program I am trying to get the program to quit when you leave the input field blank. Here's my code for the first program.
#Program that reads each player's name and golf score as input
#Save to golf.txt
outfile = open('golf.txt', 'w')
#Enter input, leave blank to quit program
while True:
name = input("Player's name(leave blank to quit):")
score = input("Player's score(leave blank to quit):")
if input ==" ":
break
#write to file golf.txt
outfile.write(name + "\n")
outfile.write(str(score) + "\n")
outfile.close()
With the second program I can't get the program to display the output I want on one line. Here's the second program.
#Golf Scores
# main module/function
def main():
# opens the "golf.txt" file created in the Golf Player Input python
# in read-only mode
infile = open('golf.txt', 'r')
# reads the player array from the file
player = infile.read()
# reads the score array from the file
score = infile.read()
# prints the names and scores
print(player + "scored a" + score)
# closes the file
infile.close()
# calls main function
main()
Any help or suggestions I can get would be greatly appreciated.
Two main problems:
1.) you first code has if input == ' ' which is wrong in two ways:
input is a function. you already saved the input so you should be comparing with name and score.
input returns a '' when you dont input anything, not a ' '.
so change to: if name == '' or score == '': or even if '' in (name,score): (does the same things)
2.) file.read() will automatically read EVERYTHING in the file as one string. You want to split it into each component so you can either do something like:
player,score = file.readlines()[:2]
or
player = file.readline()
score = file.readline()
then print (with leading and trailing spaces in your middle string!)
print(player + " scored a " + score)
Got both programs working
program 1:
#Program that reads each player's name and golf score as input
#Save to golf.txt
outfile = open('golf.txt', 'w')
#Enter input, leave blank to quit program
while True:
name = input("Player's name(leave blank to quit):")
if name == "":
break
score = input("Player's score:")
#write to file golf.txt
outfile.write(name + "\n")
outfile.write(str(score) + "\n")
outfile.close()
program 2:
#Golf Scores
# main module/function
def main():
# opens the "golf.txt" file created in the Golf Player Input python
# in read-only mode
infile = open('golf.txt', 'r')
# reads the player array from the file
name = infile.readline()
while name != '':
# reads the score array from the file
score = infile.readline()
# strip newline from field
name = name.rstrip('\n')
score = score.rstrip('\n')
# prints the names and scores
print(name + " scored a " + score)
# read the name field of next record
name = infile.readline()
# closes the file
infile.close()
# calls main function
main()
Eliminate spaces from the input before checking (I would use .strip() method). And compare it to the empty string "" instead of space(s) " ".
With the "while true" block you keep asking and taking the names and the scores, but you overwrite them so you always will have just the last pair.
You need to keep them all, so you can make a list:
names_and_scores = []
while True:
name = input("Player's name(leave blank to quit):").strip()
if name == "":
break
score = input("Player's score:").strip()
if name != "" and score != "":
names_and_scores.append("{}; {}".format(name, score))
with open('golf.txt', 'w') as outfile:
outfile.write("\n".join(names_and_scores))
The second program opens the file, read lines one by one, splits them and print:
with open('golf.txt', 'r') as infile:
for line in infile:
name, score = line.strip().split("; ")
print("{} scored a {}.".format(name, score))
I am fairly new to python and I need to make a program to ask 10 questions, save the score into a file and allow someone to read the scores in from the file.
My problem: I need to check if the person who has done the quiz already has a record in the file, and if so, I need to add their score to the end of their record.
The records should look like this:
name,score,score,score,score,
etc so they can be split using commas.
I am also looking for the simplest answer, not the most efficient. Also, if you could comment the code, it would make it much easier. Here is my code so far:
import random
import math
import operator as op
import sys
import re
def test():
num1 = random.randint(1, 10)
num2 = random.randint(1, num1)
ops = {
'+': op.add,
'-': op.sub,
'*': op.mul,
}
keys = list(ops.keys())
rand_key = random.choice(keys)
operation = ops[rand_key]
correct_result = operation(num1, num2)
print ("What is {} {} {}?".format(num1, rand_key, num2))
while True:
try:
user_answer = int(input("Your answer: "))
except ValueError:
print("Only enter numbers!")
continue
else:
break
if user_answer != correct_result:
print ("Incorrect. The right answer is {}".format(correct_result))
return False
else:
print("Correct!")
return True
print("1. Are you a student?")
print("2. Are you a teacher?")
print("3. Exit")
while True:
try:
status = int(input("Please select an option:"))
except ValueError:
print("Please enter a number!")
else:
if status not in {1,2,3}:
print("Please enter a number in {1,2,3}!")
else:
break
if status == 1:
username=input("What is your name?")
while not re.match("^[A-Za-z ]*$", username) or username=="":
username=input(str("Please enter a valid name (it must not contain numbers or symbols)."))
print ("Hi {}! Wellcome to the Arithmetic quiz...".format(username))
while True:
try:
users_class = int(input("Which class are you in? (1,2 or 3)"))
except ValueError:
print("Please enter a number!")
else:
if users_class not in {1,2,3}:
print("Please enter a number in {1,2,3}!")
else:
break
correct_answers = 0
num_questions = 10
for i in range(num_questions):
if test():
correct_answers +=1
print("{}: You got {}/{} {} correct.".format(username, correct_answers, num_questions,
'question' if (correct_answers==1) else 'questions'))
if users_class == 1:
class1 = open("Class1.txt", "a+")
newRecord = username+ "," + str(correct_answers) + "," + "\n"
class1.write(newRecord)
class1.close()
elif users_class == 2:
class2 = open("Class2.txt", "a+")
newRecord = username+ "," + str(correct_answers) + "," + "\n"
class2.write(newRecord)
class2.close()
elif users_class == 3:
class3 = open("Class3.txt", "a+")
newRecord = username+ "," + str(correct_answers) + "," + "\n"
class3.write(newRecord)
class3.close()
else:
print("Sorry, we can not save your data as the class you entered is not valid.")
EDIT:
Add this function before your "test" function:
def writeUserScore(file, name, score):
with open (file, "r") as myfile:
s = myfile.read()
rows = s.split("\n")
data = {}
for row in rows:
tmp = row.split(",")
if len(tmp) >= 2: data[tmp[0]] = tmp[1:]
if name not in data:
data[name] = []
data[name].append(str(score))
output = ""
for name in data:
output = output + name + "," + ",".join(data[name]) + "\n"
handle = open(file, "w+")
handle.write(output)
handle.close()
After that, where you have "if users_class == 1:" do this:
writeUserScore("Class1.txt", username, str(correct_answers))
Do the same for the other two else ifs.
Let me know what you think!
Try using a dictionary to hold the existing file data.
Read the file in a variable called "str" for example. And then do something like this:
rows = str.split("\n")
data1 = {}
for row in rows:
tmp = row.split(",")
data1[tmp[0]] = tmp[1:]
When you have a new score you should then do:
if username not in data1:
data1[username] = []
data1[username] = str(correct_answers)
And to save the data back to the file:
output = ""
for name in data1:
output = outupt + name + "," + ",".join(data1[name]) | "\n"
And save the contents of "output" to the file.
PS: If you are not bound by the file format you can use a JSON file. I can tell you more about this if you wish.
Hope that helps,
Alex
First, define these functions:
from collections import defaultdict
def read_scores(users_class):
"""
If the score file for users_class does not exist, return an empty
defaultdict(list). If the score file does exist, read it in and return
it as a defaultdict(list). The keys of the dict are the user names,
and the values are lists of ints (the scores for each user)
"""
assert 0 <= users_class <= 3
result = defaultdict(list)
try:
lines =open("Class%d.txt"%users_class,'r').readlines()
except IOError:
return result
for line in lines:
# this line requires python3
user, *scores = line.strip().split(',')
# if you need to use python2, replace the above line
# with these two lines:
# line = line.strip().split(',')
# user, scores = line[0], line[1:]
result[user] = [int(s) for s in scores]
return result
def write_scores(users_class, all_scores):
"""
Write user scores to the appropriate file.
users_class is the class number, all scores is a dict kind of dict
returned by read_scores.
"""
f = open("Class%d.txt"%users_class,'w')
for user, scores in all_scores.items():
f.write("%s,%s\n"%(user, ','.join([str(s) for s in scores])))
def update_user_score(users_class, user_name, new_score):
"""
Update the appropriate score file for users_class.
Append new_score to user_name's existing scores. If the user has
no scores, a new record is created for them.
"""
scores = read_scores(users_class)
scores[user_name].append(new_score)
write_scores(users_class, scores)
Now, in the last portion of your code (where you actually write the scores out) becomes much simpler. Here's an example of writing some scores:
update_user_score(1, 'phil', 7)
update_user_score(1, 'phil', 6)
update_user_score(1, 'alice', 6)
update_user_score(1, 'phil', 9)
there will be two lines in Class1.txt:
phil,7,6,9
alice,6
We read the whole file into a dict (actually a defaultdict(list)),
and overwrite that same file with an updated dict. By using defaultdict(list), we don't have to worry about distinguishing between updating and adding a record.
Note also that we don't need separate if/elif cases to read/write the files. "Scores%d.txt"%users_class gives us the name of the file.