Python only printing last data entered - python

I have an assignment to create a class that holds the name of an employee, id number, department, and job title. The user should be able to input the information for multiple employees and have all of the information printed out at the end.
The problem I am facing is that only the last employee's information is being printed out.
import pickle
import employee
data = 'data.dat'
def main():
output_file = open(data, 'wb')
end_of_file = False
keep_going = 'Y'
while keep_going == 'Y':
name = str(input('Name of employee: '))
ID_num = int(input('Employee ID number: '))
dep = str(input('Department: '))
job = str(input('Job Title: '))
emp = employee.Employee(name, ID_num)
emp.set_department(dep)
emp.set_job_title(job)
pickle.dump(emp, output_file)
keep_going = input('Enter another employee file? (Use Y / N): ')
input_file = open(data, 'rb')
while not end_of_file:
try:
emp = pickle.load(input_file)
display_data(emp)
except EOFError:
end_of_file = True
input_file.close()
if keep_going == 'N':
print(display_data(emp))
output_file.close()
def display_data(emp):
print('Name','\t','\t','ID Number','\t','Department','\t','\t','Job Title')
print(emp.get_name(), '\t', emp.get_ID_num(),'\t','\t',emp.get_department(),'\t','\t',emp.get_job_title())
main()
If anyone knows why this is happening and has any suggestions on how to fix it I would really appreciate it as I am new to python and don't fully understand all of the concepts

You need to store the employees in memory and then write to the file in the end. Also, I don't understand why you need this bit of code, it doesn't seem to be doing anything :
input_file = open(data, 'rb')
while not end_of_file:
try:
emp = pickle.load(input_file)
display_data(emp)
except EOFError:
end_of_file = True
input_file.close()
So we remove this, and make some other modifications. Your modified code :
import pickle
import employee
data = 'data.dat'
def display_data(emp):
print('Name','\t','\t','ID Number','\t','Department','\t','\t','Job Title')
print(emp.get_name(), '\t', emp.get_ID_num(),'\t','\t',emp.get_department(),'\t','\t',emp.get_job_title())
def main():
output_file = open(data, 'wb')
emp_list = []
keep_going = 'Y'
while keep_going == 'Y':
name = str(input('Name of employee: '))
ID_num = int(input('Employee ID number: '))
dep = str(input('Department: '))
job = str(input('Job Title: '))
emp = employee.Employee(name, ID_num)
emp.set_department(dep)
emp.set_job_title(job)
emp_list.append(emp)
keep_going = input('Enter another employee file? (Use Y / N): ')
pickle.dump(emp_list, output_file)
output_file.close()
if keep_going == 'N':
input_file = open(data, 'rb')
employees = pickle.load(open(data, "rb"))
for emp in employees:
print(display_data(emp))
main()
Also, the printing can be made cleaner :
from tabulate import tabulate
def display_data(employees):
infos = []
for emp in employees:
infos.append([emp.get_name(), emp.get_ID_num(), emp.get_department(), emp.get_job_title()])
print(tabulate(infos, headers=["Name", "ID num", "Department", "Job Title"], tablefmt="fancy_grid"))
So, to print, replace
for emp in employees:
print(display_data(emp))
with
display_data(employees)
HTH.

Every time pickle.dump() is called, it overwrites the existing file. So firstly you need to store all the employees in a list and then write it to file using dump().
While retrieving also you need to load data from file using pickle.load() into a list.

Related

Save input as text file in python

I got a simple python code with some inputs where a user has to type name, age, player name and his best game.
Now I want that all these inputs from the user were saved as a text file or something like this.
I tried
with open ("Test_", "a") as file:
User_input = file.write(input("here type in your name"))
I tried it with with open ... n where I create a new text file before which I open in python and add something. But everything I tried failed. Hope my English is good enough to understand what kind of problem I have.
import csv
OUTFILE = 'gameplayers.csv'
def main():
player = []
morePlayer = 'y'
while morePlayer == 'y':
name = input('Enter your name: ')
age = input('Your age: ')
playerName = input('Your player name: ')
bestGame = input('What is your best game: ')
player.append([name, age, playerName, bestGame])
morePlayer = input('Enter information of more players: (y, n): ')
with open(OUTFILE, 'a', encoding='utf_8') as f:
csvWriter = csv.writer(f, delimiter=',')
csvWriter.writerows(player)
if __name__ == '__main__':
main()
If you want to keep adding new data, use a otherwise, use w to overwrite. I've used a in this example:
name = input('Name: ')
age = input('Age: ')
best_game = input('Best Game: ')
with open('user_data.txt', 'a') as file:
file.write(f'Name: {name} - Age: {age} - Best Game: {best_game}\n')
First of all, you need to know the difference between 'a' and 'w' in with open. 'w' stands for write, meaning every time you call it, it will be overwritten. 'a' stands for append, meaning new information will be appended to the file. In your case, I would have written the code something like this
userInput = input(“Enter your name: “)
with open(“filename.txt”, “a”) as f:
f.write(userInput)
If you instead want to overwrite every time - change the 'a' to a 'w'.

No attribute present

I am quite new to python and I am getting an attribute error.
import FileHandeling as fh;
import os;
CounterFilePath = os.path.dirname(os.path.realpath(__file__))+"/counter.txt";
FilePath = os.path.dirname(os.path.realpath(__file__))+"/FileIO.txt";
class Employee:
def createEmployee(self):
numOfEmployees = int(input("Enter number of employees: "));
empDetails = [];
for i in range(numOfEmployees):
empFName, empLName, empSalary, empEmailId = raw_input("Enter employee first name: "), raw_input("Enter employee last name: "), raw_input("Enter employee salary: "), raw_input("Enter employee Email ID: ");
string = str(i)+" "+empFName+" "+empLName+" "+empSalary+" "+empEmailId+"\n";
empDetails.append(string);
with open(FilePath,"a+") as fo:
fo.seek(0);
fh.createFile(fo,numOfEmployees,empDetails,CounterFilePath);
def searchEmployee(self):
choice = int(input("Press:\n1 to search by First Name\n2 to search by Last Name\n3 to search by Salary\n4 to search by Email ID\n"));
print "Enter the",;
if(choice == 1):
print "First Name:",;
elif(choice == 2):
print "Last Name:",;
elif(choice == 3):
print "Salary:",;
elif(choice == 4):
print "Email ID:",;
searchStr = raw_input();
with open(FilePath,"r") as fo:
string = fh.readFile(fo,searchStr,choice-1);
while line in string:
print line;
def updateEmployee(self):
print "Leave the entries empty if you dont want to update that entry.";
lineNum = input("Enter the line number of the entry you want to update: ");
with open(FilePath,"r") as fo:
empFName, empLName, empSalary, empEmailId = raw_input("Enter employee first name: "), raw_input("Enter employee last name: "), raw_input("Enter employee salary: "), raw_input("Enter employee Email ID: ");
if(empFName == ""):
record = fh.readFile(fo,lineNum-1,0);
empDetails = record[0].split();
empFName = empDetails[1];
if(empLName == ""):
record = fh.readFile(fo,lineNum-1,0);
empDetails = record[0].split();
empLName = empDetails[2];
if(empSalary == ""):
record = fh.readFile(fo,lineNum-1,0);
empDetails = record[0].split();
empSalary = empDetails[3];
if(empEmailId == ""):
record = fh.readFile(fo,lineNum-1,0);
empDetails = record[0].split();
empEmailId = empDetails[4];
updateStr = str(lineNum-1)+" "+empFName+" "+empLName+" "+empSalary+" "+empEmailId+"\n";
fh.updateRecord(fo,FilePath,updateStr,lineNum-1);
def deleteEmployee(self):
lineNum = input("Enter the line number of the entry you want to delete: ");
with open(FilePath,"r") as fo:
fh.deleteRecord(fo,FilePath,lineNum-1);
def main(self):
goOn = True;
employee = Employee();
while goOn:
choice = input("Press:\n1 to enter a new employee\n2 to search employee\n3 to update employee\n4 to delete employee\n0 to exit\n");
if(choice == 1):
employee.createEmployee();
elif(choice == 2):
employee.searchEmployee();
elif(choice == 3):
employee.updateEmployee();
elif(choice == 4):
employee.deleteEmployee();
elif(choice == 0):
goOn = False;
else:
print "Wrong Choice!!!";
emp = Employee();
emp.main();
Here I am importing this class:
class FileHandeling:
def createFile(fo,numOfRecords,data,counterFile):
#Getting the value of counter
frc = open(counterFile,"r");
counter = int(frc.read());
frc.close();
#Taking input and writing to the file
for i in range(counter,numOfRecords+counter):
string = str(i)+data[i];
fo.write(string);
counter += 1;
#Writing back to counter the updated value.
fwc = open(counterFile,"w");
fwc.write(str(counter)+"\n");
fwc.close();
def readFile(fo,searchStr,criteria):
line = fo.readline();
string = [];
while line:
entries = line.split();
if(searchStr == entries[criteria]):
string.append(line);
line = fo.readline();
return string;
def printFile(fo):
fo.seek(0);
lines = fo.readlines();
print "The File: "
for line in lines:
print line;
def updateRecord(fo,fileLoc,updateStr,lineNum):
#Replacing the given record with he updated record and writing back to file
lines = fo.readlines();
fwu = open(fileLoc, "w");
lines[lineNum]= updateStr;
for line in lines:
fwu.write(line);
fwu.close();
def deleteRecord(fo,fileLoc,lineNum):
#Deleting the record
lines = fo.readlines();
fwu = open(fileLoc, "w");
lines.pop(lineNum);
#Correcting the Employee Ids and Writing Back to File
for line in lines:
entry1, entry2, entry3, entry4, entry5 = line.split();
entry1 = str(lines.index(line));
line = entry1+" "+entry2+" "+entry3+" "+entry4+" "+entry5+"\n";
fwu.write(line);
fwu.close();
#Reducing Counter value
frc = open(counterFile,"r");
counter = int(frc.read());
frc.close();
fwc = open(counterFile,"w");
fwc.write(str(counter-1)+"\n");
fwc.close();
In this code I am trying to replicate a database with the help of file but my code gives error saying that 'module' object has no attribute 'createFile'. I also tried creating packages and doing like in java but then it started saying that ImportError: No module named src.fileManipulation. they were just my folders in which I was working and wanted them as packages so I put an __init__.py in them and the tutorials said that this will help in making packages but that didn't happen and since both my files were in same directory I imported it directly but now it gives attribute error and I don't know what that means. Please Help.
I have executed the code in Python default IDLE after correcting some print statements. I am using Python3 so used print (" "). And the result was an endless loop of
Wrong Choice!!!
Press:
1 to enter a new employee
2 to search employee
3 to update employee
4 to delete employee
0 to exit
My kind requtest to you is to revise Python once again.

How to stop a csv file overwriting

this code asks a user to input a barcode, my program then opens a csv file and accesses a database , there are 4 different products, the user eneters how many of the product they want and then asks if they want to keep shopping or press 0 and stop shopping and print a receipt (which is another csv file) , my problem is that my program does not take previous orders into account and only the last one , if that makes sense (if i order 3 tomatoes and then 4 pieces of celery it only takes the amount of celery into account). I want to apoligise for poor english as it is not my primary language. Here is the part of the code which i think is going wrong
def quantity():
fileOne = open('receipt.csv', 'w')
writer = csv.writer(fileOne)
global total_price
product_data = read_csv_file()
matches = search_user_input(product_data)
if matches: # Will not be True if search_user_input returned None
print("apple")
product, price = matches[0], matches[1]
order = int(input("How much of {} do you want?".format(product)))
values = [str(product), str(price), str(order*price)]
writer.writerows((values,))
total_price.append(order * price)
continue_shopping=int(input("press 0 to stop shopping and print your reciept or press 1 to continue shopping"))
if (continue_shopping == 0):
fileOne.close()
fileTwo = open("receipt.csv" , "r")
reader = csv.reader(fileTwo)
for row in reader:
if row != None:
print(row)
elif continue_shopping==1:
quantity()
quantity()
Here is the rest of the code if you are curious.
import csv
import locale
total_price = []
locale.setlocale( locale.LC_ALL, '' )
def read_csv_file():
global total_price
""" reads csv data and appends each row to list """
csv_data = []
with open("task2.csv") as csvfile:
spamreader = csv.reader(csvfile, delimiter=",", quotechar="|")
for row in spamreader:
csv_data.append(row)
return csv_data
def get_user_input():
global total_price
""" get input from user """
while True:
try:
GTIN = int(input("input your gtin-8 number: "))
return GTIN # Breaks the loop and returns the value
except:
print ("Oops! That was not a valid number. Try again")
def search_user_input(product_data):
global total_price
repeat=""
# Pass the csv data as an argument
""" search csv data for string """
keep_searching = True
while keep_searching:
gtin = get_user_input()
for row in product_data:
if row[0] == str(gtin):
product = row[1]
price = round(float(row[2]),2)
return(product, price)
while True:
try:
repeat = input("not in there? search again? If so (y), else press enter to continue")
break
except:
print("please make sure you enter a valid string")
if repeat != 'y':
keep_searching = False
return None
def quantity():
fileOne = open('receipt.csv', 'w')
writer = csv.writer(fileOne)
global total_price
product_data = read_csv_file()
matches = search_user_input(product_data)
if matches: # Will not be True if search_user_input returned None
print("apple")
product, price = matches[0], matches[1]
order = int(input("How much of {} do you want?".format(product)))
values = [str(product), str(price), str(order*price)]
writer.writerows((values,))
total_price.append(order * price)
continue_shopping=int(input("press 0 to stop shopping and print your reciept or press 1 to continue shopping"))
if (continue_shopping == 0):
fileOne.close()
fileTwo = open("receipt.csv" , "r")
reader = csv.reader(fileTwo)
for row in reader:
if row != None:
print(row)
elif continue_shopping==1:
quantity()
quantity()
I appreciate any help or advice or if you do not understand a part of my code i can try to explain

python: Adding to username

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.

Personal archive tool, looking for suggestions on improving the code

i've written a tool in python where you enter a title, content, then tags, and the entry is then saved in a pickle file. it was mainly designed for copy-paste functionality (you spot a piece of code you like on the net, copy it, and paste it into the program), not really for handwritten content, though it does that with no problem.
i mainly did it because i'm always scanning through my pdf files, books, or the net for some coding example of solution that i'd already seen before, and it just seemed logical to have something where you could just put the content in, give it a title and tags, and just look it up whenever you needed to.
i realize there are sites online that handle this ex. http://snippets.dzone.com, but i'm not always online when i code. i also admit that i didn't really look to see if anyone had written a desktop app, the project seemed like a fun thing to do so here i am.
it wasn't designed with millions of entries in mind, so i just use a pickle file to serialize the data instead of one of the database APIs. the query is also very basic, only title and tags and no ranking based on the query.
there is an issue that i can't figure out, when you are at the list of entries there's a try, except clause where it tries to catch a valid index (integer). if you enter an inavlid integer, it will ask you to enter a valid one, but it doesn't seem to be able to assign it to the variable. if you enter a valid integer straightaway, there are no problems and the entry will display.
anyway let me know what you guys think. this is coded for python3.
main file:
#!usr/bin/python
from archive_functions import Entry, choices, print_choice, entry_query
import os
def main():
choice = ''
while choice != "5":
os.system('clear')
print("Mo's Archive, please select an option")
print('====================')
print('1. Enter an entry')
print('2. Lookup an entry')
print('3. Display all entries')
print('4. Delete an entry')
print('5. Quit')
print('====================')
choice = input(':')
if choice == "1":
entry = Entry()
entry.get_data()
entry.save_data()
elif choice == "2":
queryset = input('Enter title or tag query: ')
result = entry_query('entry.pickle', queryset)
if result:
print_choice(result, choices(result))
else:
os.system('clear')
print('No Match! Please try another query')
pause = input('\npress [Enter] to continue...')
elif choice == "3":
queryset = 'all'
result = entry_query('entry.pickle', queryset)
if result:
print_choice(result, choices(result))
elif choice == "4":
queryset = input('Enter title or tag query: ')
result = entry_query('entry.pickle', queryset)
if result:
entry = result[choices(result)]
entry.del_data()
else:
os.system('clear')
print('No Match! Please try another query')
pause = input('\npress [Enter] to continue...')
elif choice == "5":
break
else:
input('please enter a valid choice...')
main()
if __name__ == "__main__":
main()
archive_functions.py:
#!/bin/usr/python
import sys
import pickle
import os
import re
class Entry():
def get_data(self):
self.title = input('enter a title: ')
print('enter the code, press ctrl-d to end: ')
self.code = sys.stdin.readlines()
self.tags = input('enter tags: ')
def save_data(self):
with open('entry.pickle', 'ab') as f:
pickle.dump(self, f)
def del_data(self):
with open('entry.pickle', 'rb') as f:
data_list = []
while True:
try:
entry = pickle.load(f)
if self.title == entry.title:
continue
data_list.append(entry)
except:
break
with open('entry.pickle', 'wb') as f:
pass
with open('entry.pickle', 'ab') as f:
for data in data_list:
data.save_data()
def entry_query(file, queryset):
'''returns a list of objects matching the query'''
result = []
try:
with open(file, 'rb') as f:
entry = pickle.load(f)
os.system('clear')
if queryset == "all":
while True:
try:
result.append(entry)
entry = pickle.load(f)
except:
return result
break
while True:
try:
if re.search(queryset, entry.title) or re.search(queryset, entry.tags):
result.append(entry)
entry = pickle.load(f)
else:
entry = pickle.load(f)
except:
return result
break
except:
print('no entries in file, please enter an entry first')
pause = input('\nPress [Enter] to continue...')
def choices(list_result):
'''takes a list of objects and returns the index of the selected object'''
os.system('clear')
index = 0
for entry in list_result:
print('{}. {}'.format(index, entry.title))
index += 1
try:
choice = int(input('\nEnter choice: '))
return choice
except:
pause = input('\nplease enter a valid choice')
choices(list_result)
def print_choice(list_result, choice):
'''takes a list of objects and an index and displays the index of the list'''
os.system('clear')
print('===================')
print(list_result[choice].title)
print('===================')
for line in list_result[choice].code:
print(line, end="")
print('\n\n')
back_to_choices(list_result)
def back_to_choices(list_result):
print('1. Back to entry list')
print('2. Back to Main Menu')
choice = input(':')
if choice == "1":
print_choice(list_result, choices(list_result))
elif choice == "2":
pass
else:
print('\nplease enter a valid choice')
back_to_choices(list_result)
In the else, you call the main function again recursively. Instead, I'd do something like choice == "0", which will just cause the while loop to request another entry. This avoids a pointless recursion.

Categories