Having trouble with creating a variable that adds to itself - python

I have a variable in my code (named totalPrice) which will set itself to a price given and then when the user adds a product to their list it will add that price to totalPrice. However, when running it, it resets the variable to 0. I believe it has something to do with the placement of it as I have placed it inside a subprogram. I do not know what to do with it as I can't seem to find a place for it.
My code is as follows:
import csv
import sys
import re
import os
addItem = ""
gtinNum = ""
quantity = 0
restart = ""
f = open("ChocolateCSV.csv", "rt")
global receipt
receipt = open("receipt.txt", "w+")
def restart():
restart = input("Would you like to restart? Y/N")
if restart.lower() == "y":
gtinQuestion()
else:
global receiptCont
receiptCont = receipt.read()
receipt.close()
print(receiptCont)
print("Total Price: " + "%.2f" % round(totalPrice, 2))
sys.exit()
def quantityQuestion():
quantity = input("How much would you like?")
if quantity.isdigit() == False:
quantityQuestion()
global price
price = ""
global totalPrice
totalPrice = 0
with open("ChocolateCSV.csv", 'r') as file2:
for row in csv.reader(file2):
if str(gtinNum) in row:
receipt.write(str(row) + "\n")
receipt.write(str("- Quantity: " + quantity + "\n"))
price = float(row[2]) * int(quantity)
totalPrice += price
receipt.write("- Price: " + str("%.2f" % round(price, 2)) + "\n")
restart()
break
def gtinQuestion():
global gtinNum
gtinNum = input("Please enter the GTIN-8 Code of the product you would like to order:")
if gtinNum.isdigit() == False or len(gtinNum) != 8:
gtinQuestion()
elif gtinNum.isdigit() == True and len(gtinNum) == 8:
quantityQuestion()
gtinQuestion()

totalPrice is not global within restart().
also think of re-designing your code, there's a lot of dangerous recursion and global variables. E.g. if quantity.isdigit() == False: within quantityQuestion calls quantityQuestion and continues despite the error with the computation.
The whole point of having functions is to hide computation and variables inside. Use function parameters etc and learn clean python (try import this within a python console).

Related

Writing to a file in a for loop and def is not defined

In Python, This can not loop many times and cannot find ID number in def.
Every time I try to run the program I get the error
"NameError: name 'askname' is not defined"
and in textfile Keep only the latest data
I expect the output of #def new_booking to be Keep data in files continuously but the actual output is kept data in files just one sentence
I expect the output of #def pre_booked to be Extract data from a file but the actual output is
"NameError: name 'askname' is not defined"
import random
# total=0
# people=0
total1 = 0
total2 = 0
# mini bar
def mini_bar():
mini_bar_total = 0
print("£50 for the Bar")
askbar = input("Would you like a mini bar? Y/N")
if askbar.upper() == "Y":
mini_bar_total = mini_bar_total + 50
return mini_bar_total
# breakfast
def breakfast(people, asknights):
breakfast_total = 0
print("£25 for breakfast")
askdinner = input("Would you like dinner? Y/N")
if askdinner.upper() == "Y":
breakfast_total = (people * 25) * asknights
print("total: £", breakfast_total)
return breakfast_total
# dinner
def dinner(people, asknights):
dinner_total = 0
print("£25 for Dinner")
askdinner = input("Would you like dinner? Y/N")
if askdinner.upper() == "Y":
dinner_total = (people * 25) * asknights
return dinner_total
# number customers
def num_customers():
customer_total = 0
print("£50 an Adult")
askadult = int(input("How many adults? "))
customer_total = askadult * 50
print("total: £", customer_total)
print("£25 a Child")
askchild = int(input("How many children? "))
customer_total = (askchild * 25) + customer_total
print("total: £", customer_total)
return customer_total, askadult, askchild
# number of nights (multiplier)
def num_nights(customer_total):
nights_total = 0
waiting = True
while waiting == True:
try:
asknights = int(input("How many nights are you staying for? "))
nights_total = customer_total * asknights
print("total: £", nights_total)
break
except ValueError:
print("invalid input!")
return nights_total, asknights
# New Booking *********
def new_booking():
askname = str(input("Please enter your name? "))
idnumber = random.randint(100, 999)
customer_total, numAdults, numChild = num_customers()
Num_people = numAdults + numChild
nights_total, asknights = num_nights(customer_total)
askbar = mini_bar()
askbreakfast = breakfast(Num_people, asknights)
askdinner = dinner(Num_people, asknights)
total = askdinner + askbreakfast + askbar + asknights
detailslist = (idnumber, askname, numAdults, numChild, asknights, askbar, askbreakfast, askdinner)
for i in detailslist:
f = open('newbooking.txt', 'w')
f.write(str(detailslist) + '\n')
print(i)
print("your total amount is: £", total)
print("your Name & ID number is: ", askname, idnumber)
# Pre booking ***** is not defind
def pre_booked():
name = input("enter your name or ID number: ")
if name == (askname) or (idnumber):
detailslist = [idnumber, askname, askadult, askchild, asknights, askbar, askbreakfast, askdinner]
for i in detailslist:
print(i)
print("total: £", total)
# main menu, start of program.
def main_menu():
print("##################### WELCOME TO BAY HOTEL ###########################")
print('''Please see what is available at the Hotel,\nAdult Prices per night: £50pp,\nChild price: £25pp,\nMiniBar price: £50 per room,\nBreakfast: £20pp,\nDinner: £25pp''')
while True:
prebook = input("Have you booked? Y/N")
if prebook.upper() == "N":
new_booking()
elif prebook.upper() == "Y":
pre_booked()
main_menu()
- I expect the output of #def new_booking to be Keep data in files continuously but the actual output is keep data in files just one sentence
- I expect the output of #def pre_booked to be Extract data from file but the actual output is "NameError: name 'askname' is not defined"
I think it's because your way to writing data in files.
Working with files has 3 step:
1) Opening file
2) Read [from] / Write [to] file
3) Closing file
third step is what you don't handled it.
You want to write a list in file and you are opening that file in each iteration. It's not a good idea (opening and closing files have their overhead) when you can do it once.
I changed some of your new_booking function and wrote it here:
# New Booking *********
def new_booking():
askname = str(input("Please enter your name? "))
idnumber = random.randint(100, 999)
customer_total, numAdults, numChild = num_customers()
Num_people = numAdults + numChild
nights_total, asknights = num_nights(customer_total)
askbar = mini_bar()
askbreakfast = breakfast(Num_people, asknights)
askdinner = dinner(Num_people, asknights)
total = askdinner + askbreakfast + askbar + asknights
detailslist = (idnumber, askname, numAdults, numChild, asknights, askbar, askbreakfast, askdinner)
# I handled opening and closing file with [python with statement]
# It close files automatically at the end
with open('newbooking.txt', 'w') as f:
for i in detailslist:
f.write(str(detailslist) + '\n')
print(i)
print("your total amount is: £", total)
print("your Name & ID number is: ", askname, idnumber)
The problem here is that you havent actually defined askname in your pre_booked() function so you cant compare against it. In new_booking() you are asking for the username with askname = str(input("Please enter your name? ")) however in the pre_booked() case you dont so you cant use it there without first getting the values from somewhere.
Seeing that you save the new_booking() to a file you probably want to load the data from your file like this:
accounts = []
with open(r"<FILEPATH", "r") as booking_file:
for line in booking_file:
accounts.append(line)
In your new_booking function it might be better to put all the related data in line by line or maybe even use dicts so you can later be sure which values belong together instead of writing all the values into their own line. So you might want to do this instead:
with open('newbooking.txt', 'w') as booking_file:
f.write(detailslist)
Then you can read line by line and possibly use ´eval()´ to get a list or dictionary right from your string or atleast you know the values in one line belong together later on.
You might also want to consider using "a" for append instead of w for write in your bookings file depending if you want to have multiple booking values in your file or just the one.

UnboundLocalError - Python Error

I am getting the following error with my code:
UnboundLocalError: local variable 'row' referenced before assignment
I have tried many things, but nothing has worked. I suspect it is something to do around the 'quantityQuestion' subprogram. According to the scripter, the problem is at line 97.
import csv
import sys
global totalPrice
totalPrice = 0
addItem = ""
gtinNum = ""
quantity = 0
restart = ""
global receipt
receipt = open("receipt.txt", "w+")
global restockTxt
restockTxt = open("restock.txt", "w+")
global price
price = 0
global file2
file2 = open("ChocolateCSV2.csv", "r")
global file2w
file2w = open("ChocolateCSV2.csv", "w", newline="")
def restart():
restart = input("Would you like to restart? Y/N")
if restart.lower() == "y":
actionQ()
else:
print("Exiting program.")
file2.close()
sys.exit()
def priceSub(): #Defining the restart subprogram
priceQ = input("Would you like to add an item? Y/N") #Asks the user if they would like to add an item.
global totalPrice #Declaring totalPrice and making it global.
totalPrice = int(price) + totalPrice #Setting totalPrice to add the variable price to itself.
if priceQ.lower() == "y": #If statement that checks to see if the user has entered a "y".
gtinQuestion() #If it is true, it will start the gtinQuestion subprogram.
else: #Anything other than a "y" will do the following commands.
global receiptCont #Declaring the receipt content as a global variable.
receiptCont = receipt.read() #Reads the receipt.
receipt.close() #Closes the file.
print(receiptCont) #Prints the content of the receipt.
print("Total Price: " + "%.2f" % round(totalPrice, 2)) #Prints the totalPrice variable rounded to two decimal places.
restart()
def quantityQuestion(): #Defining the subprogram for the quantity.
quantity = input("How much would you like?") #Asks the user how much of the item they would like.
if quantity.isdigit() == False: #If statement to check whether or not the user has entered an integer or not.
quantityQuestion() #If they have not entered an integer, it will ask the question again.
global price #Declaring the variable price as a global variable.
price = "" #Setting price to an empty string.
reader = csv.reader(file2, delimiter = ",")
csvList = list(reader)
for row in csvList: #Loop that seperates each row in the CSV
if str(gtinNum) in row: #If statement to check if the GTIN given by the user is in the CSV.
receipt.write(str(row) + "\n") #If it is in one of the CSV rows, it will write the row to the text file.
receipt.write(str("- Quantity: " + quantity + "\n")) #It also writes the quantity given by the user.
price = float(row[2]) * int(quantity) #The price is the price given by the CSV file multiplied by the quantity.
receipt.write("- Price: " + str("%.2f" % round(price, 2)) + "\n") #The final price (after the multiplication) is written to the text file also.
row[2] = row[2] - quantity
writeCSV = csv.writer(file2w)
writeCSV.writerow(row)
file2w.close()
priceSub() #Starts the restart subprogram.
break #Breaks the loop.
else:
print("The code entered could not be found - Please re-enter") #If it is not in the CSV it will print this error message.
gtinQuestion() #Starts the gtinQuestion subprogram.
def gtinQuestion(): #Defining the gtinQuestion subprogram.
global gtinNum #Declaring the gtinNum variable as global.
gtinNum = input("Please enter the GTIN-8 Code of the product you would like to order:") #Setting that variable to the initial question.
if gtinNum.isdigit() == False or len(gtinNum) != 8: #If the code given is not an integer or is not 8 digits long...
print("Please re-enter your GTIN-8 code - Reason: Invalid Code") #It will print this error message and ask the question again.
gtinQuestion()
elif gtinNum.isdigit() == True and len(gtinNum) == 8: #If it is an integer and is 8 digits long...
quantityQuestion() #It will start the quantityQuestion subprogram.
def restockAction():
reader = csv.reader(file2, delimiter = ",")
csvList = list(reader)
for row in csvList:
stDiff = float(row[5]) - float(row[3])
if float(row[3]) <= float(row[4]):
restockTxt.write(row[0]+" | "+row[1]+" | "+"Stock Replenished: "+(str(stDiff)+"\n"))
restockTxt.close()
row[3] = row[5]
writeCSV = csv.writer(file2w)
writeCSV.writerows(csvList)
file2w.close()
else:
if float(row[3]) >= float(row[4]):
restockTxt.write("No (other) stock needs to be replenished.")
restockTxt.close()
restockRead = open("restock.txt", "r")
print(restockRead.read())
restart()
def actionQ():
restock = input("What action would you like to perform?:\n Restock (Enter 1)\n Order (Enter 2)")
if restock == "1" or restock == "restock":
print("Restock Action Requested...")
restockAction()
elif restock == "2" or restock == "order":
print("Ordering action Requested...")
gtinQuestion()
else:
actionQ()
actionQ()
Any help is appreciated,
Thanks.
The problem is in restockAction():
for row in csvList:
# some code
else:
if float(row[3]) >= float(row[4]):
# ^
If there are no rows in csvList, row will not have any value, since the for will not be executed, but the else block will be executed.
So row in the else block of the for has yet to defined.
Did you intend to attach the else to the if, not the for:
for row in csvList:
stDiff = float(row[5]) - float(row[3])
if float(row[3]) <= float(row[4]):
# ...
else:
# ...
You have to verify you have that you have any rows before checking whether row[index] has a value:
else:
if row and float(row[3]) >= float(row[4]):
restockTxt.write("No (other) stock needs to be replenished.")
restockTxt.close()
restockRead = open("restock.txt", "r")
print(restockRead.read())
restart()
if row and ... acts as a vanguard, protecting the interpreter from executing row[index]. If row is None, if row == False and it returns immediately without evaluating the rest of the statement.

IndexError: list index out of range when trying to work with a CSV

I am working with a CSV file for a program I am writing but I seem to be getting this error:
Traceback (most recent call last):
File "C:\Users\Jordan\Documents\Year 10\Computing\CA and Coursework\A453 Material 2\Task 3\Task 3.py", line 115, in <module>
actionQ()
File "C:\Users\Jordan\Documents\Year 10\Computing\CA and Coursework\A453`Material 2\Task 3\Task 3.py", line 111, in actionQ
gtinQuestion()
File "C:\Users\Jordan\Documents\Year 10\Computing\CA and Coursework\A453 Material 2\Task 3\Task 3.py", line 80, in gtinQuestion
quantityQuestion() #It will start the quantityQuestion subprogram.
File "C:\Users\Jordan\Documents\Year 10\Computing\CA and Coursework\A453 Material 2\Task 3\Task 3.py", line 52, in quantityQuestion
if float(row[3]) >= float(quantity):
IndexError: list index out of range`
I'm not quite sure how to approach it but I have never had this problem before. Initially, quantityQuestion was its own program but I have decided to place it with this other code for accessibility.
As a side note - I am unable to overwrite the third row so that the new stock can be updated in the CSV. (Any help on this is also appreciated).
Code:
import csv
import sys
global totalPrice
totalPrice = 0
addItem = ""
gtinNum = ""
quantity = 0
restart = ""
price = 0
receipt = open("receipt.txt", "w+")
restockTxt = open("restock.txt", "w+")
file = open("ChocolateCSV2.csv", "r")
def restart():
restart = input("Would you like to restart? Y/N")
if restart.lower() == "y":
actionQ()
else:
file.close()
print("Exiting program.")
sys.exit()
def priceSub(): #Defining the restart subprogram
priceQ = input("Would you like to add an item? Y/N") #Asks the user if they would like to add an item.
global totalPrice #Declaring totalPrice and making it global.
totalPrice = int(price) + totalPrice #Setting totalPrice to add the variable price to itself.
if priceQ.lower() == "y": #If statement that checks to see if the user has entered a "y".
gtinQuestion() #If it is true, it will start the gtinQuestion subprogram.
else: #Anything other than a "y" will do the following commands.
global receiptCont #Declaring the receipt content as a global variable.
receiptCont = receipt.read() #Reads the receipt.
receipt.close() #Closes the file.
print(receiptCont) #Prints the content of the receipt.
print("Total Price: " + "%.2f" % round(totalPrice, 2)) #Prints the totalPrice variable rounded to two decimal places.
restart()
def quantityQuestion(): #Defining the subprogram for the quantity.
quantity = input("How much would you like?") #Asks the user how much of the item they would like.
if quantity.isdigit() == False: #If statement to check whether or not the user has entered an integer or not.
quantityQuestion() #If they have not entered an integer, it will ask the question again.
global price #Declaring the variable price as a global variable.
price = "" #Setting price to an empty string.
with open("ChocolateCSV.csv", 'r') as file2:
for row in csv.reader(file2): #Loop that seperates each row in the CSV
if str(gtinNum) in row[0]: #If statement to check if the GTIN given by the user is in the CSV.
if float(row[3]) >= float(quantity):
receipt.write(str(row) + "\n") #If it is in one of the CSV rows, it will write the row to the text file.
receipt.write(str("- Quantity: " + quantity + "\n")) #It also writes the quantity given by the user.
price = float(row[2]) * int(quantity) #The price is the price given by the CSV file multiplied by the quantity.
receipt.write("- Price: " + str("%.2f" % round(price, 2)) + "\n") #The final price (after the multiplication) is written to the text file also.
updateStk = str(float(row[3]) - float(quantity))
row[3] = updateStk
file2w = open("ChocolateCSV2.csv", "w", newline = "")
writeCSV = csv.writer(file2w)
writeCSV.writerows(csvList)
file2w.close()
priceSub() #Starts the restart subprogram.
break #Breaks the loop.
elif float(row[3]) <= float(quantity):
print("There is not enough stock to allow you to purchase this item - Try again u nerd.")
gtinQuestion()
else:
print("The code entered could not be found - Please re-enter") #If it is not in the CSV it will print this error message.
gtinQuestion() #Starts the gtinQuestion subprogram.
def gtinQuestion(): #Defining the gtinQuestion subprogram.
global gtinNum #Declaring the gtinNum variable as global.
gtinNum = input("Please enter the GTIN-8 Code of the product you would like to order:") #Setting that variable to the initial question.
if gtinNum.isdigit() == False or len(gtinNum) != 8: #If the code given is not an integer or is not 8 digits long...
print("Please re-enter your GTIN-8 code - Reason: Invalid Code") #It will print this error message and ask the question again.
gtinQuestion()
elif gtinNum.isdigit() == True and len(gtinNum) == 8: #If it is an integer and is 8 digits long...
quantityQuestion() #It will start the quantityQuestion subprogram.
def restockAction():
reader = csv.reader(file, delimiter = ",")
csvList = list(reader)
for row in csvList:
stDiff = float(row[5]) - float(row[3])
if float(row[3]) <= float(row[4]):
restockTxt.write(row[0]+" | "+row[1]+" | "+"Stock Replenished: "+(str(stDiff)+"\n"))
row[3] = row[5]
file2w = open("ChocolateCSV2.csv", "w", newline = "")
writeCSV = csv.writer(file2w)
writeCSV.writerows(csvList)
file2w.close()
else:
restockTxt.write("No (other) stock needs to be replenished.")
restockTxt.close()
restockRead = open("restock.txt", "r") print(restockRead.read())
restart()
def actionQ():
restock = input("What action would you like to perform?:\n Restock (Enter 1)\n Order (Enter 2)")
if restock == "1" or restock == "restock":
print("Restock Action Requested...")
restockAction()
elif restock == "2" or restock == "order":
print("Ordering action Requested...")
gtinQuestion()
else:
actionQ()
actionQ()
CSV File:
12312313 Item 1 0.5 100 25 100
12345670 Item 2 0.2 100 25 100
76543210 Item 3 0.3 100 25 100
34563670 Item 4 0.4 100 25 100

How do I make my program give me the value of a certain cell in a CSV?

I am having problems with trying to make my program find a certain cell in a CSV file. My program will ask you for a 8 digit number. If it is in the CSV file, the row should be written to a text file. It then should proceed to ask the user how much of the product they want to buy. This quantity will then be multiplied to give a final price. The price will be written to a variable named totalPrice.
My initial problem is with the quantity since I cannot retrieve it from the third column of the row of the entered GTIN-8 number in my CSV file.
My code is:
import csv
import sys
import re
import os
addItem = ""
gtinNum = ""
quantity = 0
totalPrice = 0
restart = ""
f = open("ChocolateCSV.csv", "rt")
def restart():
restart = input("Would you like to restart? Y/N")
if restart.lower() == "y":
gtinQuestion()
else:
print(receiptCont)
sys.exit()
def quantityQuestion():
quantity = input("How much would you like?")
def scanGTIN():
global rows
rows = re.split('\n', f.read())
global receiptCont
receiptCont = receipt.read()
for index, row in enumerate(rows):
global cells
cells = row.split(',')
if gtinNum in cells:
receipt.write(receiptCont)
receipt.close()
quantityQuestion()
def gtinQuestion():
global gtinNum
global receipt
receipt = open("receipt.txt", "r+")
gtinNum = input("Please enter the GTIN-8 Code of the product you would like to order:")
if gtinNum.isdigit() == False or len(gtinNum) != 8:
gtinQuestion()
elif gtinNum.isdigit() == True and len(gtinNum) == 8:
scanGTIN()
gtinQuestion()
You could just iterate through the lines of the csv file and return a particular column of the row that contains the 8 digit number:
import csv
def get_row(filename, number, column):
with open(filename, 'r') as f:
for row in csv.reader(f):
if str(number) in row:
return row[column+1]

Function is not getting called

I have below code where I have two functions print_menu() and pStockName()
def print_menu():
print ("\t\t\t\t 1. Get Stock Series ")
print ("\t\t\t\t 2. Invoke Stocks.")
print ("\t\t\t\t 3. Generate DC Stock List . ")
print ("\t\t\t\t 4. QUIT")
def pStockName():
global StockList, fStockList
pStockList = []
fStockList = []
StockList = str(raw_input('Enter pipe separated list of StockS : ')).upper().strip()
items = StockList.split("|")
count = len(items)
print 'Total Distint Stock Count : ', count
items = list(set(StockList.split("|")))
# pipelst = StockList.split('|')
# pipelst = [i.split('-mc')[0] for i in StockList.split('|')]
# pipelst = [i.replace('-mc','').replace('-MC','').replace('$','').replace('^','') for i in StockList.split('|')]
pipelst = [i.replace('-mc', '').replace('-MC', '').replace('$', '').replace('^', '') for i in items]
# pipelst = [Stock.rsplit('-mc',1)[0] for Stock in pipelst]
filepath = '/location/Stock_data.txt'
f = open(filepath, 'r')
for lns in f:
split_pipe = lns.split(':', 1)
if split_pipe[0] in pipelst:
index = pipelst.index(split_pipe[0])
pStockList = split_pipe[0] + "|"
fStockList.append(pStockList)
del pipelst[index]
# f.close()
for lns in pipelst:
print bcolors.red + lns, ' is wrong Stock Name' + bcolors.ENDC
if lns:
uResp = str(raw_input('Do You Want To Continue with option 0 [YES|Y|NO|N] : ')).upper().strip()
if uResp == "NO" or uResp == "N":
os.system("tput clear")
print bcolors.FAIL + "\n PLEASE USE OPTION 0 TO ENTER THE Stock NAMES BEFORE PROCEEDING." + bcolors.ENDC
# StockList = None
print_menu()
else:
pStockName()
f.close()
In above code you must be seeing in 4th last line I am calling print_menu() function. But it is just printing the content of print_menu() function not doing any operation and going to pStockName() function. Follow operation I want to execute from print_menu() function when I am calling it:
while choice >= 1 and choice < 4:
if choice == 4:
os.system("tput clear")
if StockList:
uResp = str(raw_input(
bcolors.FAIL + 'Do you need to move : ' + StockList + ' ? Press Y To Go Back to Main Menu and N to Quit [YES|Y|NO|N] : ')).upper()
if uResp == "NO" or uResp == "N":
print bcolors.HEADER + "GoodBye." + bcolors.ENDC
break
I mean to say when I am calling print_menu() function in pStockName() function in 4th last line from pStockName() function it should print the content of print_menu() function and when I press 4 it should perform the operation quit. But when I pressing any of the option from 1 to 4 it going to pStockName() function only.
Please help me what I am doing wrong here.
I'm a bit new here, but I do not see where you assign the keyboard input into variable "choice". Therefore, the program will not recognize what the end user input is. My suggestion is to assign "choice" into raw_input Like so:
choice = raw_input()
if choice == "4": # alternatively, perform int(choice) == 4
print ("yes")
I hope this helps!

Categories