Working on a homework problem. Have almost all of the code working but for some reason cant seem to get my program to save and exit properly.
here is the prompt given.
You should create a program that manages a tab-separated text file containing employees travel expenses. There are 4 and only 4 employees who travel for the company: alice, bob, carl, and diane. Each record in the data file will contain an employee name, a destination city, miles traveled, and gallons used.
For full credit:
Your program should properly read and store the given data to and from the tab-separated data file. That is, I should be able to use your program with my data file without error.
When the data is read into your program it should be organized as a list of dictionaries, where each dictionary is a row in the file, using these dictionary keys: name, city, miles, gallons.
You need to add functionality to display the user's name, total miles traveled, total gallons used, average mpg, and the expense of the total miles at 75 cents per mile. This should work for any of the 4 proper user names you enter.
You do not need to do any data validation unless just want to.
If and only if your program runs exactly like it should, I will add a 10 point bonus if, rather than using concatenation, you properly use the python CSV module to read and write the data to and from the file, converting the tab-separated data to a dictionary and vice versa.
You need to use the base code provided by the lecture notes, more or less. All 4 menu options should work.
Use formatting to have everything line up in neat columns for display option 1.
My problem is that I cannot get the 4th option "Save and exit" to function properly.
def read_file(travels):
salesperson_list = []
with open("travels.txt", 'r') as infile:
for line in infile.readlines():
line = line.strip().split('\t')
d = {}
d['name'] = line[0]
d['city'] = line[1]
d['miles'] = eval(line[2])
d['gallons'] = eval(line[3])
salesperson_list.append(d)
return salesperson_list
def display_all_data(data):
print('{0:<8}{1:<15}{2:<8}{3:<8}'.format('Name', 'City', 'Miles', 'Gallons'))
for row in data:
print('{0:<8}{1:<15}{2:^8}{3:^8}'.format(row.get('name'), row.get('city'), \
row.get('miles'), row.get('gallons')))
def calculate_user_data(data):
name = input('Enter user name: ').lower()
total_miles = sum([row.get('miles') for row in data if row.get('name') == name])
total_gallons = sum([row.get('gallons') for row in data if row.get('name') == name])
cities = [row.get('city') for row in data if row.get('name') == name]
mpg = total_miles/total_gallons
owed = mpg*0.75
print('Total miles travelled: {0}'.format(total_miles))
print('Total gallons used: {0}'.format(total_gallons))
print('mpg = ',mpg)
print('expense = $', owed, 'at 75 cents per mile')
def add_a_trip(data):
name = input('Input name: ').lower()
city = input('Input city travelled: ').lower()
miles = eval(input('Enter miles travelled: '))
gallons = eval(input('Enter gallons used: '))
d = {}
d['name'] = name
d['city'] = city
d['miles'] = miles
d['gallons'] = gallons
data.append(d)
print('Data added successfully')
def save_And_exit(data):
with open('F:\\travels.txt','w') as outfile:
for row in data:
outfile.write(row.get('name')+'\t'+row.get('city')+'\t'+\
str(row.get('miles'))+'\t'+str(row.get('gallons'))+'\n')
print('Saved to file')
def menu(salesperson_list):
print('Menu options. Choose 1, 2, 3, or 4')
print('[1] Display all trip data')
print('[2] Calculate user data')
print('[3] Add a trip')
print('[4] Save an exit')
while True:
choice = input('Enter choice --> ')
if choice == '1':
display_all_data(salesperson_list)
elif choice == '2':
calculate_user_data(salesperson_list)
elif choice == '3':
add_a_trip(salesperson_list)
elif choice == '4':
save_And_exit(salesperson_list)
print('Bye')
break
else:
print('Invalid selection')
def main():
salesperson_list = read_file('F:\\travels.txt')
menu(salesperson_list)
main()
I just need my program to save and exit properly with no global variables
Related
im fairly new to handling files so im just confused
#pretend this is a text file, do not modify this part of the code.....
emps='''20120001;Tortor;Griffin;Manager;Admin;1000;5000
20120002;Sebastian;Jest;Assist. Manager;Admin;750;3000'''
f = open('empList.txt','w')
f.write(emps)
f.close()
#Code here
employees = []
while True:
print('''1 - Show Employees
2 - Increase Salary to employees
X - Exit
''')
choice = input('Enter your choice: ')
print()
if choice =='2':
with open('empList.txt', 'r') as f:
employees = f.read().splitlines()
for employee in employees:
emp_num, last, first, position, dept, salary, allowance = employee.split(';')
if position == 'Manager':
print(f'{emp_num} {last} {first} {float(salary)*2} {dept} {allowance} {position}')
else:
print(f'{emp_num} {last} {first} {float(salary)*1.5} {dept} {allowance} {position}')
print()
elif choice =='1':
with open('empList.txt', 'r') as f:
employees = f.read().splitlines()
for employee in employees:
emp_num, last, first, position, dept, salary, allowance = employee.split(';')
print(f'{emp_num} {last} {first} {float(salary)} {dept} {allowance} {position}')
print()
elif choice =='X':
break
my problem is whenever I input Choice 2 the changed values for salary is not permanent, so whenever I change the values by inputting Choice 2, it still shows the unchanged values, how do I fix this?
probably because I'm using a print statement but I'm in a stump as to what function I'm supposed to use here, I thought of using append but it would just make a copy of the data, what am I missing?
so something like this is the problem.
1 - Show Employees
2 - Increase Salary to employees
X - Exit
Enter your choice: 2
20120001 Tortor Griffin 2000.0 Admin 5000 Manager
20120002 Sebastian Jest 1125.0 Admin 3000 Assist. Manager
1 - Show Employees
2 - Increase Salary to employees
X - Exit
Enter your choice: 1
20120001 Tortor Griffin 1000.0 Admin 5000 Manager <---Value didn't change to 2000.0?
20120002 Sebastian Jest 750.0 Admin 3000 Assist. Manager <---Value didn't change to 1125.0?
1 - Show Employees
2 - Increase Salary to employees
X - Exit
First thing is you are opening the file with 'r', which is in read-only mode. You need to change it to 'w', like: with open('empList.txt', 'w').
Second thing is you are not writing anything to the file, you are just printing it. You miss f.write(...) in the choices.
You can create a copy of the new data and then write it back to the file using write() function something like below. Note that the code is not tested but the approach should help you figure out the solution.
if choice =='2':
with open('empList.txt', 'r') as f:
employees = f.read().splitlines()
# create a new list to store modified employee data
modified_employees = []
for employee in employees:
emp_num, last, first, position, dept, salary, allowance = employee.split(';')
if position == 'Manager':
# Append current employee record with modified salary to the new list
modified_employees.append("{};{};{};{};{};{};{}".format(emp_num, last, first, position, dept, salary*2, allowance))
print(f'{emp_num} {last} {first} {float(salary)*2} {dept} {allowance} {position}')
else:
# Append current employee record with modified salary to the new list
modified_employees.append("{};{};{};{};{};{};{}".format(emp_num, last, first, position, dept, salary*1.5, allowance))
print(f'{emp_num} {last} {first} {float(salary)*1.5} {dept} {allowance} {position}')
# Write the new list back to file. This will overwrite previous content and keeps the fresh
with open('empList.txt', 'w') as f:
for each_record in modified_employees:
f.write("{}\n".format(each_record))
So long story short, I have been working on a Python program and I have been trying to get what the user inputs into the program to a txt file - I received some help online overall, but a bit stumped here.. Need it to include index, make, model, color, year and mileage of the vehicles that have been input (basically what is visible in the output when user hits "4" at main menu). The idea is when user hits "6" , that list/ data will be exported to txt file named "Vehicle Inventory" and then Exit the application. The issue is definitely around end of code at elif ch == 6: ... Any assistance or resolution on this would be appreciated !! Here is what I have so far:
# automobile class
class automobile:
# constructor
def __init__(self, make="", model="", color="", year=2018, mileage=0):
self.make = make
self.model = model
self.color = color
self.year = year
self.mileage = mileage
# setter methods
def set_make(self, make):
self.make = make
def set_model(self, model):
self.model = model
def set_color(self, color):
self.color = color
def set_year(self, year):
self.year = year
def set_mileage(self, mileage):
self.mileage = mileage
# getter methods
def get_make(self):
return self.make
def get_model(self):
return self.model
def get_color(self):
return self.color
def get_year(self):
return self.year
def get_mileage(self):
return self.mileage
# end of automobile class
# method to add a new vehicle to the inventory
def add_vehicle(v_list):
make = input("Enter make: ")
model = input("Enter model: ")
color = input("Enter color: ")
year = int(input("Enter year: "))
mileage = int(input("Enter mileage: "))
v = automobile(make, model, color, year, mileage)
v_list.append(v)
print("*** VEHICLE ADDED SUCCESSFULLY...")
# method to remove a vehicle from the inventory
def remove_vehicle(v_list):
index = int(input("Enter the index # of vehicle you would like to remove: "))
if index >= 0 and index < len(v_list):
make = v_list[index].get_make()
model = v_list[index].get_model()
v_list.pop(index)
print(make, model, "HAS BEEN REMOVED FROM INVENTORY !")
else:
print("*** INVALID INDEX #... PLEASE TRY AGAIN")
# method to update a vehicle info in the inventory
def update_vehicle(v_list):
index = int(input("Enter the index # of vehicle you would like to update: "))
if index >= 0 and index < len(v_list):
make = input("Enter new make: ")
model = input("Enter new model: ")
color = input("Enter new color: ")
year = int(input("Enter new year: "))
mileage = int(input("Enter new mileage: "))
v_list[index].set_make(make)
v_list[index].set_model(model)
v_list[index].set_color(color)
v_list[index].set_year(year)
v_list[index].set_mileage(mileage)
print("*** UPDATED SUCCESSFULLY !")
else:
print("*** INVALID INDEX #... PLEASE TRY AGAIN")
# method to print all vehicle details in proper formatted order
def display_vehicles(v_list):
print('{:10} {:10} {:10} {:10} {:10} {:10}'.format('INDEX #', 'MAKE', 'MODEL', 'COLOR', 'YEAR', 'MILEAGE'))
for i in range(len(v_list)):
v = v_list[i]
print('{:10} {:10} {:10} {:10} {:10} {:10}'.format(str(i), v.get_make(), v.get_model(), v.get_color(), str(v.get_year()), str(v.get_mileage())))
v_list = [] # initial list
# looping infinitely
while True:
# showing menu
print("1. Add a vehicle")
print("2. Remove a vehicle")
print("3. Update a vehicle")
print("4. Display all vehicle inventory")
print("5. Exit")
print("6. Export to 'Vehicle Inventory' txt file and Exit")
# getting choice
ch = int(input("*** PLEASE CHOOSE AN OPTION: "))
# performing actions based on choice
if ch == 1:
add_vehicle(v_list)
elif ch == 2:
remove_vehicle(v_list)
elif ch == 3:
update_vehicle(v_list)
elif ch == 4:
display_vehicles(v_list)
elif ch == 5:
break;
elif ch == 6:
with open('Vehicle Inventory.txt', 'w') as filehandle:
for display_vehicles in v_list:
filehandle.write("%s\n" % display_vehicles)
break;
else:
print("*** INVALID OPTION... PLEASE TRY AGAIN")
Executing your code, the txt file contains lines such as
<__main__.automobile object at 0x0000017F5E7017C0>.
The problem is that at line filehandle.write("%s\n" % display_vehicles) pass an object reference as data to be written to the file. As far as I know, there is no ready-made function that allows you to pass a file an object reference and have the data auto-extracted from it. If you really want to use a txt file, you can do something like this:
with open('Vehicle Inventory.txt', 'w') as filehandle:
for display_vehicles in v_list:
filehandle.write("make: {}, model: {}, color: {}, year: {}, mileage:{} \n".format(display_vehicles.get_make(),display_vehicles.get_model(),display_vehicles.get_color(),display_vehicles.get_year(),display_vehicles.get_mileage()))
Output
make: car, model: a, color: red, year: 2020, mileage:20
make: car2, model: b, color: black, year: 10, mileage: 10
A brief explanation of Format.
Format allows you to insert values into a string using a style based on placeholders. {} correspond to anonymous placeholders: this means that the value that goes in that position depends on the order used inside .format(value1, value2, ...).
Alternatively, you can use named placeholders such as:
"my car is {color} and i bought it in {year}".format(color= "red", year= 2010)
About the txt file
Personally I would not use a txt file, especially since loading data from this type of file can be quite annoying in cases where you are only interested in a few rows or a certain value of each row (e.g.: all red cars). I don't know if the txt file is mandatory for you, so I won't provide any detailed info on the following alternative methods. In any case, you should know that there are other types of files that are widely used for storing information.
Json. The data are stored into a dictionary, i.e. a set of key-value pairs. Reading and writing files is trivial thanks to the json module
Csv. This is very similar to a txt but has a more structured form, as if it were a table. Each row corresponds to a record, each record consists of columns. Thanks to pandas, it is easy to use csv to extract subsets of data based on the value contained in the records or the row index. The file structure also allows you to quickly create graphs and export data to Excel.
Pickle. If you don't even care about human-friendly representation but just want to save the data permanently to a file, you could try pickle
Hello everyone so I have an issue trying to find the user input in a dictionary.
My function is getting data from a website and writing it to a text file. Then transferred into a dictionary, from there I will ask the user to input a country name and it will return the key and the value of that key or the capita income. The issue i am having is that i have to search the dictionary to find the input and if it matches the key then it will print that and the capita income. Im not 100 percent sure what to use if i should use a for function or if my code is correct at the end.
def main():
import requests
webFile = "https://www.cia.gov/library/publications/the-world-factbook/rankorder/rawdata_2004.txt"
data = requests.get(webFile) #connects to the file and gest a response object
with open("capital.txt",'wb') as f:
f.write(data.content) #write the data out to a file – wb used since thecontent from the response object is returned as abinary object.
f.close()
countryName = {}
with open('capital.txt','r') as infile:
for line in infile:
num,*key,value = line.split()
key = ' '.join(key)
countryName[key] = value.upper()
userInput = input("Enter a country name: ")
userInput.upper()
while(userInput != 'stop'):
#for loop to see if key is in dictionary
if userInput in countryName:
#if(userInput == countryName[key]):
print("The per capita income in",key, "is",countryName[key])
userInput = input("Enter a country name: ")
main()
while(userInput != 'stop'):
#for loop to see if key is in dictionary
if userInput in countryName:
#if(userInput == countryName[key]):
print("The per capita income in",key, "is",countryName[key])
userInput = input("Enter a country name: ")
main()
Here is where the issue is, tying to find the if the userInput is the same as the country name key . What would i have to do search the dictionary to match the key to the input, or if there is any uneccesary things in my code.
Update 2
Ah, there was a small issue when comparing the keys. Actually, you were doing upper() on the value (a number) which doesn't make sense.
Have a look at this update:
import requests
webFile = "https://www.cia.gov/library/publications/the-world-factbook/rankorder/rawdata_2004.txt"
data = requests.get(webFile)
with open("capital.txt",'wb') as f:
f.write(data.content)
countryName = {}
with open('capital.txt','r') as infile:
for line in infile:
num, *key, value = line.split()
key = ' '.join(key)
countryName[key.upper()] = value #key.upper() instead of value.upper()
userInput = input("Enter a country name: ").upper()
counter = 0
while not userInput == "STOP": #'STOP' because it's uppercase
if userInput in countryName:
print("The per capita income in", userInput, "is", countryName[userInput])
userInput = input("Enter a country name: ").upper()
counter += 1
if counter >= len(countryName): #It couldn't find the country
userInput = input("Not found. Enter a new country: ").upper()
counter = 0 #Let's try again
And a small improvement: the counter will prevent the infinite loop when the user input doesn't satisfy the if userInput in countryName and it's not "stop". Besides that, the "stop" condition must be "STOP", once it'll be in upper case.
Hope it helps
Update
As pointed out by #Barmar, another possibility is:
countryName = {
"countryA": "valueA",
"countryB": "valueB"
}
userInput = "countryA" #Of course, it can be a user input
if userInput in countryName:
print ("The country is", userInput, "and the value is", countryName[userInput])
Just a good advice: I think the file part has nothing to do with your question itself, so, next time try to reduce your problem to, you know, something more direct :)
Anyway, you can loop over the keys of countryName and then compare with the user input. In other words:
countryName = {
"countryA": "valueA",
"countryB": "valueB"
}
userInput = "countryA" #Of course, it can be a user input
for key in countryName.keys():
if userInput == key: #Got it
print ("The country is", key, "and the value is", countryName[key])
Hope it helps
Using python I am trying to make it where the books in a text file display and the user can select a book and a quantity and do this in a loop. As they do this it is supposed to save it to a text file as a receipt and print it out when the user is done making their selections. This is what I've been able to accomplish so far.
cusName = input("What is your name?")
def main():
def menu():
print("Here is a list of items that we have:")
books_file= open("Books.txt","r")
lines = books_file.readlines()
aryBooks = []
for line in lines:
print(line)
bookChoice = input("Which book would you like?")
bookQty = input("You chose", bookChoice , "How many would you like?")
print ("Qty:", bookQty)
print ("Item:", bookChoice)
price = print ("Price:", book[2])
print ("SubTotal:", price * bookQty)
repeat = input("Would you like another item? Y or N")
receipt_file= open("receipt.txt","w")
lines = receipt_file.writelines()
for i in range(0,len(aryBooks)):
print(i + 1, aryBooks[i])
Try the code below:
def menu():
# Main loop for shopping
cart = {}
# Read books here
books = read_books()
while True:
# Loop until user does not want to shop any longer
print("Here is a list of items that we have:\n")
for book_num, (book_name, book_price) in books.items():
print(f'#{book_num}: {book_name} -- ${book_price}')
bookChoice = input("Which book would you like? (Please enter a number)\n")
# Make sure user enters the right number
try:
price = books[bookChoice][1]
except:
print('Sorry you chose the wrong number')
print()
continue
bookQty = int(input(f"You chose {books[bookChoice][0]}. How many would you like?\n"))
subtotal = price * bookQty
cart[books[bookChoice][0]] = (bookQty, subtotal)
print (f"Qty: {bookQty}")
print (f"Item: {books[bookChoice][0]}")
print (f"Price: {price}")
print (f"SubTotal: {subtotal}")
repeat = input("Would you like another item? Y or N\n")
# End loop if answer was No
if repeat.lower() == 'n' or repeat.lower == "no":
print(f'Your total was: {sum([y for x, y in cart.values()])}')
generate_receipt('receipt.txt', books, cart)
print('Have a good day!\n')
break
else:
print('Here is what you have thus far:')
for name, (qty, sub) in cart.items():
print(f'Name: {name} ; Qty: {qty} ; Subtotal: {sub}')
print()
def generate_receipt(path_to_receipt, books, cart):
# Generate receipt based on shopping cart
with open(path_to_receipt, 'a') as receipt_file:
for name, (qty, subtotal) in cart.items():
receipt_file.write(f'Qty: {qty} ; Item: {name}; Total: {sum([y for x, y in cart.values()])}; Subtotal: {subtotal}\n')
def main():
# Main loop that starts the shopping
cusName = input("What is your name?\n")
print(f'Hi {cusName}. Welcome to the bookstore!')
menu()
def read_books(path_to_books="Books.txt"):
# Read in the books from the file
with open(path_to_books, 'r') as f:
books = f.readlines()
books = [book.strip().split(',') for book in books]
books = {book_num: (book_name, int(book_price)) for book_num, book_name, book_price in books}
return books
if __name__ == '__main__':
main()
The output file might not be what you want but that can be fixed really easily.
My Books.txt is as follows:
15,Harry Potter,20
2,LOTR,25
I am working through the chapter exercises in Tony Gaddis's "Starting Out With Python" 3rd edition from a class I have taken previously. I'm in chapter 9 and Exercise 8 requires me to write a program that pickles a dictionary (name:email) to a file when it closes and unpickles that file retaining the data when it is opened. I have read every word in that chapter and I still don't understand how you can do both in the same file. When you use the open function it creates a file which, in my understanding, is a new file with no data. I'm thinking it may be a sequencing issue, as in where to put the dump and load lines of code but that doesn't make sense either. Logic dictates you have to open the file before you can dump to it.
If the 'open' function creates a file object and associates it with a file and this function appears early in the code (as in def main), what keeps it from zeroing out the file each time that line is called?
This is not a homework assignment. I have completed that class. I am doing this for my own edification and would appreciate any explanation which would help me to understand it. I have included my attempt at the solution which is reflected in the code below and will keep gnawing at it until I find the solution. I just thought since the gene pool is deeper here I would save myself some time and frustration. Thank you very much to those that choose to reply and if I am lacking in any pertinent data that would help to clarify this issue, please let me know.
import pickle
#global constants for menu choices
ADDNEW = 1
LOOKUP = 2
CHANGE = 3
DELETE = 4
EXIT = 5
#create the main function
def main():
#open the previously saved file
friends_file = open('friends1.txt', 'rb')
#friends = pickle.load(friends_file)
end_of_file = False
while not end_of_file:
try:
friends = pickle.load(friends_file)
print(friends[name])
except EOFError:
end_of_file = True
friends_file.close()
#initialize variable for user's choice
choice = 0
while choice != EXIT:
choice = get_menu_choice() #get user's menu choice
#process the choice
if choice == LOOKUP:
lookup(friends)
elif choice == ADDNEW:
add(friends)
elif choice == CHANGE:
change(friends)
elif choice == DELETE:
delete(friends)
#menu choice function displays the menu and gets a validated choice from the user
def get_menu_choice():
print()
print('Friends and Their Email Addresses')
print('---------------------------------')
print('1. Add a new email')
print('2. Look up an email')
print('3. Change a email')
print('4. Delete a email')
print('5. Exit the program')
print()
#get the user's choice
choice = int(input('Enter your choice: '))
#validate the choice
while choice < ADDNEW or choice > EXIT:
choice = int(input('Enter a valid choice: '))
#return the user's choice
return choice
#the add function adds a new entry into the dictionary
def add(friends):
#open a file to write to
friends_file = open('friends1.txt', 'wb')
#loop to add data to dictionary
again = 'y'
while again.lower() == 'y':
#get a name and email
name = input('Enter a name: ')
email = input('Enter the email address: ')
#if the name does not exist add it
if name not in friends:
friends[name] = email
else:
print('That entry already exists')
print()
#add more names and emails
again = input('Enter another person? (y/n): ')
#save dictionary to a binary file
pickle.dump(friends, friends1.txt)
friends1.close()
#lookup function looks up a name in the dictionary
def lookup(friends):
#get a name to look up
name = input('Enter a name: ')
#look it up in the dictionary
print(friends.get(name, 'That name was not found.'))
#the change function changes an existing entry in the dictionary
def change(friends):
#get a name to look up
name = input('Enter a name: ')
if name in friends:
#get a new email
email = input('Enter the new email address: ')
#update the entry
friends[name] = email
else:
print('That name is not found.')
#delete an entry from the dictionary
def delete(friends):
#get a name to look up
name = input('Enter a name: ')
#if the name is found delete the entry
if name in friends:
del [name]
else:
print('That name is not found.')
#call the main function
main()
If you open a file for reading with open("my_file","r") it will not change the file. The file must already exist. If you open a file for writing with open("my_file","w") it will create a new file, overwriting the old one if it exists. The first form (reading) is the default so you can omit the second "r" argument if you want. This is documented in the Python standard library docs.
Use open("myfile", 'r+') this allows both read and write functions. (at least in 2.7)