python basic phonebook application with IO - python

I had a basic phone book application that adds, lookup, updates, and deletes a record and it works fine. I wanted to add functionality to it in which when I close and restart the program the previously added records are still there saved in a file. And when I want to add more records to the dictionary file it will also be appended to the file but I am running into 2 issues the first one is when I try to integrate my saved file with my dictionary I get error dictionary update sequence element #0 has length 1; 2 is required so I for some reason can't read the file to check if I have a record in the file with the same name for example. The second issue is when I Quit the program I added a save Record function which when run adds the newly added records onto the file to save it before it quits but when I print it, it only shows the first string printed the other is not shown I don't know what is causing this. Any help is appreciated thanks in advance.
#!/usr/bin/python3
import os.path
from os import path
phones = {}
if path.exists('phones.txt'):
with open("phones.txt") as f:
phones = dict(x.rstrip().split(None, 1) for x in f)
else:
phoneFile = open("phones.txt", "w")
print("File Created")
phoneFile.close()
with open("phones.txt") as f:
phones = dict(x.rstrip().split(None, 1) for x in f)
def menu():
print("1. Add a record")
print("2. Lookup a record")
print("3. Update a record")
print("4. Remove a record")
print("5. List all records")
print("6. Quit")
selection = input("Please make your selection from the options above: ")
if(selection == '1'):
addRecord()
menu()
elif(selection == '2'):
lookupRecord()
menu()
elif(selection == '3'):
updateRecord()
menu()
elif(selection == '4'):
removeRecord()
menu()
elif(selection == '5'):
listRecords()
menu()
elif(selection == '6'):
saveRecords()
print("Goodbye")
#exit(0)
else:
print("Sorry, invalid input, try again.")
menu()
def addRecord():
a = str(input("Person's name to add to record: "))
b = int(input("Number to add to record: "))
if a in phones:
print("Name already in records, Please choose another name")
else:
phones[a] = b
print(phones)
def lookupRecord():
a = str(input("Person's name to look: "))
if a in phones:
print(a + "'s number is " + str(phones.get(a)))
else:
print("Person not found")
def updateRecord():
a = str(input("Person's name to update: "))
if a in phones:
b = int(input("New phone number to update: "))
phones[a] = b
print(phones)
else:
print(a + " is not in your phone book")
def removeRecord():
a = str(input("Person's name to remove: "))
if a in phones:
del phones[a]
print(a + " removed from phone book")
else:
print("Name not found")
def listRecords():
for i in phones.items():
print(i)
def saveRecords():
for i in phones.items():
writePhoneFile = open("phones.txt", "w")
finalRecord = ':'.join('%s' %id for id in i)
writePhoneFile.write(finalRecord)
readPhoneFile = open("phones.txt", "r+")
print(readPhoneFile.read())
def main():
print("== Welcome to the Phonebook App ==")
menu()
if __name__ == "__main__":
main()

use below because phone number in integer :
phones = dict( (x.rstrip().split(':')[0] , int(x.rstrip().split(':')[1])) for x in f)
in addition, open the file outside for loop in saverecords:
writePhoneFile = open("phones.txt", "w")
for i in phones.items():
print(i)
finalRecord = ':'.join('%s' %id for id in i)+'\n'
writePhoneFile.write(finalRecord)
writePhoneFile.close()

Related

Delete a line (name, contactnumber, emailaddress) by just searching for name in a phonebook

Good evening, I have a phonebook code but I am missing the delete feature. I cannot seem to make the delete feature work. All other features like insert, view, add contacts are working already.
I created a phnoebook txt file to store any entries.
phonebook = "d://phonebook.txt"
pbfile = open(phonebook, "a+")
pbfile.close
def show_main_menu():
''' Show main menu for Phone List '''
print("\n *** Phone List Menu ***\n"+
"------------------------------------------\n"+
"Enter 1, 2, 3 or 4:\n"+
"1: Display Your Contacts Records\n" +
"2: Add a New Contact Record\n"+
"3: Search your contacts\n"+
"4: Delete a Contact Record\n"+
"5: Quit\n**********************")
choice = input("Enter your choice: ")
if choice == "1":
pbfile = open(phonebook, "r+")
file_contents = pbfile.read()
if len(file_contents) == 0:
print("Phone List is empty")
else:
print (file_contents)
pbfile.close
user_entry = input("Press Enter to Return to Main Menu ...")
show_main_menu()
elif choice == "2":
enter_contact_record()
user_entry = input("Press Enter to Return to Main Menu ...")
show_main_menu()
elif choice == "3":
search_contact_record()
user_entry = input("Press Enter to Return to Main Menu ...")
show_main_menu()
elif choice == "4":
delete_contact_record()
user_entry = ("Please Enter to Return to Main Menu ...")
show_main_menu()
elif choice== "5":
print("Thanks for using Phone List")
else:
print("Wrong choice, Please Enter [1 to 5]\n")
user_entry = input("Press Enter to Return to Main Menu ...")
show_main_menu()
I added the main menu above to show the menu of the phone book, there should be another choice to delete a contact.
The following code is to search for contact. It will show if a contact is already in the phone book but will mention not on record if there is no contact by the name they searched.
def search_contact_record():
''' This function is used to searches a specific contact record '''
contact_search = input("Enter First name to search for contact record: ")
contact_search = contact_search.title()
pbfile = open(phonebook, "r+")
file_contents = pbfile.readlines()
found = False
for line in file_contents:
if contact_search in line:
print("You searched for:", end=" ")
print (line)
found=True
break
if found == False:
print("There's no contact Record in Phone List with name = " + contact_search )
The next function is to enter contact and add it to the phonebook txt file created in the beginning.
def enter_contact_record():
''' It collects contact info firstname, last name, email and phone '''
first = input('Enter First Name: ')
first = first.title()
last = input('Enter Last Name: ')
last = last.title()
phone = input('Enter Phone number: ')
email = input('Enter E-mail: ')
contact = ("[" + first + " " + last + ", " + phone + ", " + email + "]\n")
pbfile = open(phonebook, "a")
pbfile.write(contact)
print( "This contact\n " + contact + "has been added successfully!")
#def delete_contact():
show_main_menu()
I got confused on the part how to delete the contact from the txt phonebook. Last delete lines I have trying was the following
def delete_contact_record():
#Initiate a name variable
contact_delete = input('Enter the name of the contact you wish to delete: ').title()
pbfile = open(phonebook, "r+")
file_contents = pbfile.readlines()
found = False
for line in file_contents:
if contact_delete in line:
confirm = input('Are you sure you wish to delete '+contact_delete+' y/n?: ')
print(confirm)
if confirm == 'y':
del phonebook[contact_delete]
found = True
if found == False:
print('That contact does not exist! Return to the main menu to enter the contact')
it works up to the line asking for confirmation y/n. But when I enter Y, I get a TypeError: 'str' object does not support item deletion
Thank you.
Your main problem is that your phone book is a flat file. As such, a deletion is "rewrite the entire file, but without the deleted record."
This is, needless to say, very inefficient.
You will also have problems in the future with spurious matches for searches, since contact_search in line is perfectly happy to match parts of names.
Personally, I'd recommend using an SQLite3 database instead of a flat file (SQLite3 support is built in to Python). SQLite3 databases are actually single files, but you can use almost all of the SQL language to perform structured queries, and let it manage the file for you.
If writing SQL is too daunting, the SQLAlchemy Python package can help by making database tables work like Python classes.

How to manage inventory: add, remove, modify/update , search, and print

sorry if this is not presented well. This is my first time ever using StackOverflow. I'm trying to create this to keep track of inventory. I do not know how to utilize try-excepts. Additionally, I don't know what else is going wrong. Thanks for any and all help !
data handler:
import os
class DataHandler():
def __init__(self, filename, datadict = {}):
self.filename = filename
self.datadict = datadict
def readData(self): # returns dictionary
try:
fileobj = open(self.filename,'r')
datastr = fileobj.read()
fileobj.close()
# return dictionary read from file or null dictionary
if datastr != '':
return eval(datastr)
else:
return self.datadict
except FileNotFoundError:
return self.datadict # null dictionary
def writeData(self, datadict): # must pass dictionary
fileobj = open(self.filename,'w')
fileobj.write(str(datadict))
fileobj.close()
separate file:
import DataHandler as DH
def menuDisplay():
print("="*40)
print("1 - Add inventory item")
print("2 - Modify inventory item")
print("3 - Delete inventory item")
print("4 - Print inventory list")
print("5 - Exit program")
print("="*40)
selection = input("\nPlease enter menu choice: ")
if selection < "1" and selection > "5":
input("Invalid selection, please enter 1 - 5")
menuDisplay()
else:
return int(selection)
def addItem(invDict,dh):
itemdesc = input("Item Description: ")
itemqty = int(input("Qty: "))
if len(invDict) > 0:
nextKey = sorted(invDict.keys())[-1]+1
else:
nextKey = 1
invDict[nextKey]=[itemdesc,itemqty]
dh.writeData(invDict)
def printInv(invDict):
print("{:<10}{:20}{:6}".format("Item #", "Description", "Qty",))
for dkey, lvalue in invDict.items():
print("{:<10}{:20}{:6d}".format(str(dkey), lvalue[0],lvalue[1], lvalue[2]))
def delItem(invDict,dh):
itemnum = input("Please enter item to delete: ")
del invDict[int(itemnum)]
dh.writeData(invDict)
# complete error checking
def modItem(invDict,dh):
itemnum = input("Please enter item to modify: ")
newqty = input("Please enter the new quantity: ")
invDict[int(itemnum)][1] = int(newqty)
dh = DH.DataHandler("inventory.txt")
invDict = dh.readData()
selection = 0
while selection != 5:
selection = menuDisplay()
if selection == 1:
addItem(invDict,dh)
elif selection == 2:
modItem(invDict,dh)
elif selection == 3:
delItem(invDict,dh)
elif selection == 4:
printInv(invDict)

Adding a error message in Python as well as commands

#!/usr/bin/env python3
import csv
# a file in the current directory
FILENAME = "contacts.csv"
def write_contacts(contacts):
with open(FILENAME, "w", newline="") as file:
writer = csv.writer(file)
writer.writerows(contacts)
def read_contacts():
contacts = []
with open(FILENAME, newline="") as file:
reader = csv.reader(file)
for row in reader:
contacts.append(row)
return contacts
def list_contacts(contacts):
for i in range (len(contacts)):
contact= contacts[i]
print(str(i+1) +"."+ contact[0])
print()
def view_contact(contacts):
pos = int(input("Number: "))
if not (pos-1)in range(len(contacts)):
print(str(pos) + ' not in list, try again')
view(contacts)
return
contact = []
print(name + email + phone+".\n")
print()
def delete_contact(contacts):
index = int(input("Number: "))
contact = contacts.pop(index -1)
write_contacts(contacts)
print(contact[0]+" was deleted.\n")
def add_contact(contacts):
name=input("Name: ")
email=input("Email: ")
phone=input("Phone number: ")
contact= []
contact.append(name)
contact.append(email)
contacts.append(contact)
write_contacts(contacts)
print(name + " was added.\n")
def display_menu():
print("Contact Manager")
print()
print("COMMAND MENU")
print("list - List all contacts")
print("view - View a contact")
print("add - Add a contact")
print("delete- Delete a contact")
print()
print()
def main():
display_menu()
contacts = read_contacts()
while True:
command = input("Command: ")
if command.lower() == "list":
list_contacts(contacts)
elif command.lower()== "view":
view_contact(contacts)
elif command.lower()== "add":
add_contact(contacts)
elif command.lower()== "delete":
delete_contact(contacts)
break
else:
print("Not a valid command. Please try again.\n")
print("Bye!")
if __name__ == "__main__":
main()
This all my code. I'm trying to figure out how to make the delete and view commands display an error message when the user enters a number that is invalid but it's not working. I'm also trying to view a contact when the user selects a specific number form list which would then display the email name and phone number of that selected number. I'm currently stuck
The errors im getting are
raceback (most recent call last):
, line 93, in
main()
, line 81, in main
view_contact(contacts)
, line 32, in view_contact
view(contacts)
NameError: name 'view' is not defined
I don't think you has a good start with list into cvs using append, anyway is your example.
You can use remove to remove your contact from list, see examples with list: http://www.thegeekstuff.com/2013/06/python-list
when the user select a specific number from list , just read by stepping to the number phone because you add with: name + email + phone.
adding an error message , use: try except finally

Attribute Error when importing dictionary from module to another

So I have 4 different classes which I need to combine into one class at the end in a program called "Main" . However whenever I run the Main program, it keeps throwing up an attribute error when it comes to accessing the emp_det dictionary from the Employee class into the other classes so I can use the generated Employee ID stored in the dictionary. (There are two more classes called Weekly_Paid and Timecard but I've only mentioned 3 for the sake of the brevity and because the error seems to be universal).
(All 3 classes are in different files.)
The error I keep getting:
Traceback (most recent call last):
File "C:/Users/Saloni/Documents/Case Sudy 3/MAIN.py", line 28, in <module>
s.MaintainTimecard()
File "C:/Users/Saloni/Documents/Case Sudy 3\Monthly_Paid.py", line 24, in MaintainTimecard
if emp_id in Employee.emp_det:
AttributeError: module 'Employee' has no attribute 'emp_det'
Employee Class:
# ATTRIBUTES: emp_nm, emp_ph, emp_add,emp_id, emp_dob
from random import *
class Employee:
emp_det={} #dictioary to save the details of the employees
#emp_id:[emp_nm,emp_ph,emp_add,emp_dob]
def add_emp(self):
lst=[] #to store all inputed details
print("Enter Employee Details:")
emp_nm=input("Name: ")
emp_ph=input("Contact Number: ")
emp_add=input("Address: ")
emp_dob=input("Date of Birth:")
lst.extend([emp_nm,emp_ph,emp_add,emp_dob]) #store the details
emp_id="emp"+str(randrange(1000,10000))
while emp_id in Employee.emp_det: # avoid repetition
emp_id="emp"+str(randrange(1000,10000))
Employee.emp_det[emp_id]=lst # make dictionary key and store in list
print("Your Employee ID is",emp_id)
def del_emp(self):
t=0 # to count number of invalid inputs
while t<=3:
emp_id=input("Employee ID:")
if emp_id in Employee.emp_det:
del Employee.emp_det[emp_id]
t=4 # to get the program out of the loop
else:
print("Invalid ID. Try Again.")
t+=1
def edit_emp(self):
t=0 # counting invalid inputs
while t<=3:
emp_id=input("Employee ID:")
if emp_id in Employee.emp_det: # checking validity
print("\n Edit: \n 1.Contact \n 2.Address \n")
ch=int(input("Option:"))
if ch==1:
Employee.emp_det[emp_id][1]=input("New Contact Number:")
elif ch==2:
Employee.emp_det[emp_id][2]=input("New Address:")
else:
print("Invalid Option")
t=4 #t o get the program out of the loop
else:
print("Invalid ID. Try Again.")
t+=1
def Edisplay(self):
print("The Employees are:")
print(" ID \t Name \t Contact \t Address \t Date of Birth")
for i in Employee.emp_det: # access to each dictionary element
print(i,"\t",end=" ")
for j in Employee.emp_det[i]: # access every value under the key
print(j,"\t",end=" ")
print("\n")
Monthly-Paid Class
import Employee
import Timecard
class Monthly_Paid:
fixSalary = 40000
def AcceptTimeCard (self):
print ("Timecard details are:")
for i in Timecard.emp_tcinfo:
print(i, "\t", end ="")
for j in Timecard.emp_tcinfo[i]:
print(j,"\t",end=" ")
def Gen_Paycheck (self):
emp_id = input("please enter employee ID")
if emp_id in Employee.emp_det:
print ("Total Salary of " + emp_id + " is :" + fixSalary)
def MaintainTimecard (self):
emp_id = input("Please enter your employee ID")
if emp_id in Employee.emp_det:
print("\n 1.Edit Start Time Hour "
"\n 2.Edit Start Time Minute "
"\n 3. Edit End Time Hour "
"\n 4.Edit End Time Minute")
ch = int(input("Input option"))
if ch == 1:
Timecard.emp_tcinfo[emp_id][1] = input(
"Input new Start Time Hour")
if ch ==2:
Timecard.emp_tcinfo[emp_id][2] = input(
"Input new Start Time Minute")
if ch == 3:
Timecard.emp_tcinfo[emp_id][3] = input(
"Input new End Time Hour")
if ch == 4:
Timecard.emp_tcinfo[emp_id][4] = input(
"Input new End Time Minute")
else:
print("Invalid input")
Main script
print ("Welcome to Employee Time Card System")
import Employee
e= Employee.Employee()
e.add_emp()
print("What kind of employee are you?")
print ("\n 1.Monthly Paid \n 2.Weekly Paid")
ch= int(input("Enter Choice"))
if ch ==1:
import Monthly_Paid
import Timecard
s = Monthly_Paid.Monthly_Paid()
w = Timecard.Timecard()
print("Monthly Paid")
t1= "y"
while t1=="y" or t1=="Y":
print ("\n 1.See Time Card \n2.Edit TimeCard \n 3.See Paycheck")
ch1 = int(input("Enter Choice"))
if ch1 == 1:
s.AcceptTimeCard
if ch1 == 2:
s.MaintainTimecard()
if ch1 == 3:
s.Gen_Paycheck()
else:
print("Invalid Choice")
t1 = input("Continue with Monthly Paid? Y/N")
elif ch == 2:
import Weekly_Paid
a= Weekly_Paid.Weekly_Paid()
t2= "y"
print ("Weekly Paid")
while t2=="y" or t2=="Y":
print ("\n 1.See Time Card \n2.Edit TimeCard \n 3.See Paycheck")
ch1 = int(input("Enter Choice"))
if ch1 == 1:
a.AcceptTimeCard()
if ch1 == 2:
a.MaintainTimeCard()
if ch1 == 3:
a.Gen_Paycheck()
else:
print("Invalid Choice")
t2 = input("Continue with Weekly Paid? Y/N")
else:
print("Invalid choice")
import Employee will look for a module Employee.py. If there is no file called Employee.py then you won't be able to make that import work.
So in the Monthly-Paid Class file you have to do something like:
from path.to.employee_file_name import Employee
The problem then arises from the fact that there's a module called Employee but that contains a class called Employee. Importing the module Employee doesn't give you access to the class automatically. To access the attribute of the
Employee class called emp_det you have to specify the class. So if you imported using
from Employee import Employee
To access you need:
Employee.emp_det
Alternatively if you imported with:
import Employee
then to access you need:
Employee.Employee.emp_det

Pickle file with many objects

I cannot get my file to store multiple instances of contacts. After adding new contact and trying to print them, it comes up with "IndexError: list index out of range" error. What shall I do to make it work?
import pickle
class People():
def __init__(self, name, surname, age, mobile_no, home_no):
self.name = name
self.surname = surname
self.age = age
self.mobile_no = mobile_no
self.home_no = home_no
def DisplayContacts(self):
print("First Name: \t", self.name)
print("Surname: \t", self.surname)
print("Age: \t", self.age)
print("Mobile Number: \t", self.mobile_no)
print("Home Number: \t", self.home_no)
print()
def addContact():
newname = str(input("First name: \t"))
newsurname = str(input("Surname: \t"))
newage = int(input("Age: \t"))
newmobile_no = int(input("Mobile Number: \t"))
newhome_no = int(input("Home Number: \t"))
newContact = People(newname, newsurname, newage, newmobile_no, newhome_no)
return newContact
cont = 1
contacts = []
while cont == 1:
user = input("Do you want to add contact? (Y/N)")
if user == "Y" or user == "y":
print ("works")
contacts.append(addContact())
file = open("CList.pickle", "ab")
pickle.dump(contacts, file, pickle.HIGHEST_PROTOCOL)
file.close()
else:
print ("111")
cont = 0
useropen = input("open file? (Y/N)")
if useropen == "Y" or useropen == "y":
with open ("CList.pickle", "rb") as pickled_file:
contacts = pickle.load(pickled_file)
print(contacts[0].surname)
print(contacts[1].surname)
else:
print("Null")
Simply appending a picked object to a file is not the same thing as pickling a list. EAch time you append, you've created another pickled record. Read the file multiple times to get your list:
with open ("CList.pickle", "rb") as pickled_file:
contacts = []
try:
while True:
contacts.append(pickle.load(pickled_file))
except EOFError:
pass
Now, instead of appending the list of contacts (which would give you a list of lists with many duplicates), just pickle the new contact:
with open("CList.pickle", "ab") as _file:
while True:
user = input("Do you want to add contact? (Y/N)")
if user == "Y" or user == "y":
print ("works")
pickle.dump(addContact(), _file, pickle.HIGHEST_PROTOCOL)
else:
print ("111")
break

Categories

Resources