KeyError for key that exists in dictionary [closed] - python
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I have a piece of code that has an array that loops through an array of keys for a dictionary. It gets each of these keys, applies it to the dictionary and then gets the returned value and uses it for spacing out my unicode table. Example:
sizeDict = {
"Name": 16,
"Mobile": 11,
"Pizza": 7,
"Drink": 7,
"Dessert": 7,
"Total": 7
}
header = ['name', 'mobile', 'pizza', 'drink', 'dessert', 'total']
def printRow(firstChar, endChar, space, specialChar, spaceArray, spaceDict):
output = firstChar
for i in range(0, len(spaceArray)):
if(i == len(spaceArray) - 1):
specialChar = endChar
output = output + space * spaceDict[spaceArray[i].title()] + specialChar
return output
print(printRow("┏", "┓", "━", "┳", header, sizeDict))
#Returns ┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┓
The problem for some reason, is that it doesn't recognise some of the values from the array as actual keys in the dictionary, even though both strings are exactly alike. Here is the specific array, dictionary and error message where the error occured.
statHeader = ['Average Total', 'Earned', '% of Total']
statSizeDict = {
"Average Total": 15,
"Earned": 10,
"% of Total": 20
}
statSizeArray = [15,10,20]
"""
<ipython-input-3-5c5f25401e4d> in statOrders(statData)
272 for i in range(0, len(statHeader)):
273 tempString += spaceVal(statHeader[i], statSizeDict[statHeader[i]])
--> 274 print(printRow("┏", "┓", "━", "┳", statHeader, statSizeDict))
275 print(tempString)
276 print(printRow("┣", "┫", "━", "╋", statHeader, statSizeDict))
<ipython-input-3-5c5f25401e4d> in printRow(firstChar, endChar, space, specialChar, spaceArray, spaceDict)
51 if(i == len(spaceArray) - 1):
52 specialChar = endChar
---> 53 output = output + space * spaceDict[spaceArray[i].title()] + specialChar
54 return output
55 # ========================================================================================================================== #
KeyError: '% Of Total'
"""
Here is the complete code for reference:
import csv
import os
# ========================================================================================================================== #
data = []
testData = [8001, 499382, 'int', 'int', 'float']
header = ['name', 'mobile', 'pizza', 'drink', 'dessert', 'total']
statHeader = ['Average Total', 'Earned', '% of Total']
# ========================================================================================================================== #
orderDict = {
"Small cheese pizza": ['pizza', 5],
"Big cheese pizza": ['pizza', 10],
"Small drink": ['drink', 1],
"Large drink": ['drink', 1.5],
"Small dessert": ['dessert', 0.5],
"Large dessert": ['dessert', 1]
}
posDict = {
"Pizza Total": 2,
"Drink Total": 3,
"Dessert Total": 4
}
returnDict = {
1: 'Task completed succesfully.',
2: 'Task encountered an unexpected error.',
3: 'No file data was found.',
4: 'Value does not exist or is out of range.',
5: 'Value type is invalid or does not exist in current range.',
6: 'Value length was to large for function.'
}
sizeDict = {
"Name": 16,
"Mobile": 11,
"Pizza": 7,
"Drink": 7,
"Dessert": 7,
"Total": 7
}
statSizeDict = {
"Average Total": 15,
"Earned": 10,
"% of Total": 20
}
statSizeArray = [15,10,20]
def spaceVal(value, size):
return str(value)[:size] + " " * (size-len(str(value))) + '┃'
def printRow(firstChar, endChar, space, specialChar, spaceArray, spaceDict):
output = firstChar
for i in range(0, len(spaceArray)):
if(i == len(spaceArray) - 1):
specialChar = endChar
output = output + space * spaceDict[spaceArray[i].title()] + specialChar
return output
# ========================================================================================================================== #
def newOrderCash(appendData, name, mobile, pizza=0, drink=0, dessert=0):
"""
Appends the formatted order to the data list and returns
the name of the customer and the total of their order.
Args:
appendData - a list which has the order
appended to the end of it.
name - a string value containing the customer's name.
mobile - a string or integer value which contains
the mobile number of the person making the order.
pizza - the total cost of the ordered pizza which
defaults to zero if no pizza was ordered.
drink - the total cost of the ordered pizza which
defaults to zero if no pizza was ordered.
dessert - the total cost of the ordered pizza which
defaults to zero if no pizza was ordered.
Returns:
A list containing the name of the customer and the
total cost of their order.
None - If name or mobile is not provided.
"""
if(name is None or name == "" or mobile is None or mobile == ""):
return None
if(len(name) > 21 or len(str(mobile)) > 10):
return 6
total = float(pizza) + float(drink) + float(dessert)
appendData.append([name, str(mobile), float(pizza), float(drink), float(dessert), total])
returnData = name, total
return list(returnData)
def newOrderItems(appendData, name, mobile, items):
"""
Appends the formatted order to the data list and returns
the name of the customer and the total of their order.
Args:
appendData - a list which has the order
appended to the end of it.
name - a string value containing the customer's name.
mobile - a string or integer value which contains
the mobile number of the person making the order.
items - a list which contains the items the
customer has ordered.
Returns:
A list containing the name of the customer and the
total cost of their order.
None - If name or mobile is not provided.
"""
if(name is None or name == "" or mobile is None or mobile == ""):
return None
total = 0
drink = 0
dessert = 0
pizza = 0
for i in items:
total += float(orderDict[i][1])
if(orderDict[i][0] == 'pizza'):
pizza += float(orderDict[i][1])
elif(orderDict[i][0] == 'drink'):
drink += float(orderDict[i][1])
elif(orderDict[i][0] == 'dessert'):
dessert += float(orderDict[i][1])
tempArray = name, str(mobile), pizza, drink, dessert, total
appendData.append(list(tempArray))
returnData = name, total
return list(returnData)
def newBulkOrders(appendData, names, mobiles, items):
"""
Appends the formatted order to the data list and returns
the names of the customer and the totals of their order.
Args:
appendData - a list which has the order
appended to the end of it.
name - a list containing the customers' names.
mobiles - a list containing the customers' mobiles.
items - a list of lists containing.
Returns:
A list containing the names of the customers
and the totals of their orders.
None - If name or mobile is not provided.
Task Code 4 - If a type error occurs.
"""
if(names is None or names == "" or mobiles is None or mobiles == ""):
return None
try:
returnTotals = []
returnNames = []
errorArray = []
returnList = []
for l in range(0, len(names)):
total = 0
drink = 0
dessert = 0
pizza = 0
tempItems = items[l]
for i in tempItems:
total += float(orderDict[i][1])
if(orderDict[i][0] == 'pizza'):
pizza += float(orderDict[i][1])
elif(orderDict[i][0] == 'drink'):
drink += float(orderDict[i][1])
elif(orderDict[i][0] == 'dessert'):
dessert += float(orderDict[i][1])
tempArray = names[l], str(mobiles[l]), float(pizza), drink, dessert, total
returnTotals.append(total)
returnNames.append(names[l])
errorArray.append(list(tempArray))
for x in range(0, len(errorArray)):
appendData.append(errorArray[x])
returnList = returnNames, returnTotals
return list(returnList)
except IndexError:
return 4
# ========================================================================================================================== #
def saveOrder(saveData, filename):
"""
Opens a file with name filename, and writes
saveData to it.
Args:
saveData - the list of orders which will be
written to the file.
filename - a string value which gives the name
of the file to be written to.
Returns:
Task Code 1 - If the task is complete successfully.
"""
writeFile = csv.writer(open(filename, 'w', newline=''))
writeFile.writerow(header)
for i in range(0, len(saveData)):
writeFile.writerow(saveData[i])
return 1
def getOrders(writeData, filename):
"""
Opens a file with name filename, and writes
saveData to it.
Args:
saveData - the list of orders which will be
written to the file.
filename - a string value which gives the name
of the file to be written to.
Returns:
Task Code 1 - If the task is complete successfully.
"""
if os.path.isfile("pythoncsv.csv"):
getFile = csv.reader(open(filename, 'r+', newline=''))
for i in getFile:
writeData.append(i)
# Getting rid of header row so that we don't get a bunch of TypeErrors.
writeData.pop(0)
for i in writeData:
i[2] = float(i[2])
i[3] = float(i[3])
i[4] = float(i[4])
i[5] = float(i[5])
print(writeData)
else:
# Creates file as above if statement tests whether it exists or not.
getFile = csv.reader(open(filename, 'w', newline=''))
return 1
# ========================================================================================================================== #
def printOrders(printData):
# Purpose of first for loop is to ensure that longer names do not cause printing errors.
space = 0
tempString = "┃"
for i in range(0, len(header)):
tempString += spaceVal(header[i].title(), sizeDict[header[i].title()])
print(printRow("┏", "┓", "━", "┳", header, sizeDict))
print(tempString)
print(printRow("┣", "┫", "━", "╋", header, sizeDict))
tempString = ""
for i in range(0, len(printData)):
tempString = "┃"
for x in range(0, len(printData[i])):
tempString += spaceVal(printData[i][x], sizeDict[header[x].title()])
print(tempString)
print(printRow("┗", "┛", "━", "┻", header, sizeDict))
print('\n')
return 1
# ========================================================================================================================== #
def statOrders(statData):
#try:
statArray = [[0, 'Pizzas'], [0, 'Drinks'], [0, 'Desserts'], [0, 'Overall']]
for i in range(0, len(statData)):
statArray[0][0] += statData[i][2]
statArray[1][0] += statData[i][3]
statArray[2][0] += statData[i][4]
statArray[3][0] += statData[i][5]
space = 0
tempString = "┃"
for i in range(0, len(statHeader)):
tempString += spaceVal(statHeader[i], statSizeDict[statHeader[i]])
print(printRow("┏", "┓", "━", "┳", statHeader, statSizeDict))
print(tempString)
print(printRow("┣", "┫", "━", "╋", statHeader, statSizeDict))
tempString = ""
for i in range(0, len(statArray)):
tempString = "┃"
tempString = tempString + spaceVal(statArray[i][1], statSizeArray[0]) + spaceVal(str(statArray[i][0]), statSizeArray[1]) + spaceVal(str(int(100 * statArray[i][0] / statArray[3][0])) + '%', statSizeArray[2])
print(tempString)
print(printRow("┗", "┛", "━", "┻", statHeader, statSizeDict))
print('\n')
return 1
#except (IndexError, TypeError):
# return 5
# ========================================================================================================================== #
def modifyOrder(modifyData, orderName, modifyValueType, newValue):
try:
for i in range(0, len(modifyData)):
if(modifyData[i][0] == orderName):
modifyData[i][posDict[modifyValueType]] = float(newValue)
modifyData[i][5] = float(sum(modifyData[i][2:5]))
return modifyData[i][5]
return 4
except (TypeError, IndexError):
return 2
# ========================================================================================================================== #
# End of Asserts: Task Failed Succesfully
# ========================================================================================================================== #
And the specific function where the error occurs:
def statOrders(statData):
#try:
statArray = [[0, 'Pizzas'], [0, 'Drinks'], [0, 'Desserts'], [0, 'Overall']]
for i in range(0, len(statData)):
statArray[0][0] += statData[i][2]
statArray[1][0] += statData[i][3]
statArray[2][0] += statData[i][4]
statArray[3][0] += statData[i][5]
space = 0
tempString = "┃"
for i in range(0, len(statHeader)):
tempString += spaceVal(statHeader[i], statSizeDict[statHeader[i]])
print(printRow("┏", "┓", "━", "┳", statHeader, statSizeDict))
print(tempString)
print(printRow("┣", "┫", "━", "╋", statHeader, statSizeDict))
tempString = ""
for i in range(0, len(statArray)):
tempString = "┃"
tempString = tempString + spaceVal(statArray[i][1], statSizeArray[0]) + spaceVal(str(statArray[i][0]), statSizeArray[1]) + spaceVal(str(int(100 * statArray[i][0] / statArray[3][0])) + '%', statSizeArray[2])
print(tempString)
print(printRow("┗", "┛", "━", "┻", statHeader, statSizeDict))
print('\n')
return 1
#except (IndexError, TypeError):
# return 5
# ========================================================================================================================== #
In fact
"% of Total".title() returns % Of Total.
This explains your error
Related
list out of range how can i fix this and app;y the score
machine_specs = [] for spec in ("Name", "Speed in MHz", "Cores", "Cache in kB", "RAM in GB"): data_set = [] data_val = input(f"{spec}: ") if spec == "Speed in MHz": data_val = float(data_val) elif spec != "Name": data_val = int(data_val) data_set.append(data_val) machine_specs.append(data_set) def score_machine(data): score = ( data[1] / 3 * 25 + data[2] / 8 * 25 + data[3] / 32 * 25 + data[4] / 8 * 25 ) return round(score) for ms in machine_specs: print(f"{ms[0]} scores {score_machine(ms)} out of 100") this is supposed to give a score based on the data you input into the program to give a score out of a hundred based on your specifications their is a problem though
You are assigning data_set = [] in each iteration, So change like this. I think you might also be required to add another loop to get more data into machine_specs. machine_specs = [] data_set = [] for spec in ("Name", "Speed in MHz", "Cores", "Cache in kB", "RAM in GB"): data_val = input(f"{spec}: ") if spec == "Speed in MHz": data_val = float(data_val) elif spec != "Name": data_val = int(data_val) data_set.append(data_val) machine_specs.append(data_set)
Python Convert Inches and Feet into Inches
I am trying to convert arrays that contain both Inches and Feet into Inches. The feet are denoted with a single quote (') and inches are denoted with double quotes ("). The data comes in the following forms: [8'x10'] [60\" x 72\"] [5'x8',5x8,60\"x92\"] [8'10\"x12'] What I want: ["96x120"] ["60x72"] ["60x96","60x96","60x96","60x92"] ["106x144"] What I have: def ft_inch(numbers): if str(numbers).find("x") > -1: numbers=numbers.replace('[','').replace('"','').replace('[','').replace(']','') try: nom = numbers.split("x")[0] nom=nom.replace(r'\\|\"|\]|\[','') nom_one = nom.split("'")[0] nom_two = nom.split("'")[1] den = numbers.split("x")[1] den=den.replace(r'\\|\"|\[|\]','') den_one = den.split("'")[0] den_two = den.split("'")[1] ft=int(nom_one)*12 inch=nom_two.replace(r'\"| |\\','') try: inch=int(inch) except: print('B') tmp = int(ft)+int(inch) fts=int(den_one)*12 inchs=den_two.replace(r'\"| |\\','') try: inchs=int(inchs) except: print('B') tmp_two = int(fts)+int(inch) return f'["{tmp}x{tmp_two}"]' except: return numbers else: return numbers x="[5'1x8'1]" ft_inch(x) This works for a single array as long as it has both feet and inches but fails if its only feet [8'x8']. If anyone has a simpler solution please let me know
A regex-based approach: import re inputs = [["8'1x10'1"], ["60\" x 72\""], ["5'x8'", "5x8", "60\"x92\""], ["8'10\"x12'"]] for inpt in inputs: sub_output = [] for measurement in inpt: m = re.match(r"(\d+['\"]?)(\d+['\"]?)?x(\d+['\"]?)(\d+['\"]?)?", "".join(measurement.split())) groups = [m.groups()[:2], m.groups()[2:]] result_inches = [0, 0] for i, group in enumerate(groups): for raw_val in group: if raw_val == None: continue if '"' in raw_val: result_inches[i] += int(raw_val[:-1]) elif "'" in raw_val: result_inches[i] += int(raw_val[:-1])*12 else: result_inches[i] += int(raw_val)*12 sub_output.append(result_inches) print([f"{x}x{y}" for x, y in sub_output]) Output: ['108x132'] ['60x72'] ['60x96', '60x96', '60x92'] ['106x144'] I saw your edit and included the ["8'1x10'1"] case :)
I rewrote the entire thing, but this seems to work: input_ = ["8'x10'", "60\" x 72\"", "5'x8'","5x8","60\"x92\"", "8'10\"x12'", "8'1x10'1\""] inches_only = [] for s in input_: s.replace(" ", "") sides = s.split("x") new_sides = [] for side in sides: inches = 0 split1 = side.split("'") if len(split1) > 1 or (len(split1) == 1 and not side.__contains__('"')): inches = int(split1[0]) * 12 split2 = side.split('"') if len(split2) > 1: inches += int(split2[0].split("'")[-1]) elif len(split2) == 1 and len(split1) > 1 and len(split1[1]) > 0: inches += int(split1[1]) new_sides.append(str(inches) + '"') inches_only.append("x".join(new_sides)) print(inches_only) Output: ['96"x120"', '60"x72"', '60"x96"', '60"x96"', '60"x92"', '106"x144"', '97"x121"']
Taking values from one file and after some calculation and a bit changes need to print into another file in python
below is c.txt CO11 CSE C1 8 CO12 ETC C1 8 CO13 Electrical C2 12 CO14 Mech E 5 my program needs to print a course summary on screen and save that summary into a file named cr.txt. Given the above c.txt, your program output should look like below. The content of course_report.txt should also be the same, except the last line. Course names in the second column use * to indicate a compulsory course and – to indicate an elective course. The fourth column is the number of students enrolled in that course. The fifth column is the average score of the course. CID Name Points. Enrollment. Average. ---------------------------------- CO11 * CSE 8 2 81 CO12 * ETC 8 10 71 CO13 * Electrical 12 8 61 CO14 - Mech 5 4 51 ---------------------------------- poor-performing subject is CO14 with an average 51. cr.txt generated! below is what I've tried: def read(self): ctype = [] fi = open("c.txt", "r") l = fi.readline() while l != "": fields = l.strip().split(" ") self.c.append(fields) l = fi.readline().strip() f.close() # print(f"{'CID'}{'Name':>20}{'Points.':>16}{'Enrollment.':>18}{'Average.':>10}") # print("-" * 67, end="") print() for i in range(0, len(self.c)): for j in range(len(self.c[i])): obj = self.c[i][j] print(obj.ljust(18), end="") print() print("-" * 67, end="") print()
you can try use 'file.read' or 'file.readlines' after use 'open' function, if you choose 'file.readlines' you'll have to use 'for row in file.readlines()' look my example with 'file.read': headers = ['CID', 'Name', 'Points.', 'Enrollment.', 'Average.'] compulsory_course = ['CO11', 'CO12', 'CO13'] elective_course = ['CO14'] count = 0 with open('c.txt', 'r') as file_c: file_c.seek(0, 0) file_string = file_c.read().replace('\n', ' ') fields = file_string.split(' ') with open('cr.txt', 'w') as file_cr: for field in headers: file_cr.write(f'{field} ') file_cr.write('\n') for v in fields: if count == 4: file_cr.write('\n') count = 0 count += 1 if v in compulsory_course: file_cr.write(f'{v} * ') continue elif v in elective_course: file_cr.write(f'{v} - ') continue elif count == 3: file_cr.write(f' ') continue file_cr.write(f'{v} ')
Unable to break infinite loop
There are various posts related to infinite loops on here but none reflect my particular predicament (they deal with Java or they do not match my code format etc). The code I have used is actually source code or 'answer code' to an exercise aimed at new students such as myself and it only supplies the 'correct code without correct format' which for an independent student can complicate things but also provide a more productive challenge. The code makes solid use of 'functions' and 'calling functions from within other functions' which leaves very little 'global code' as a result, this may make things slightly more complicated but hopefully experienced programmers won't be phased by this. I think the loop is either an issue with my 'while loop code indentation' or the 'while loop condition/counter code itself'. The loop code takes and uses data from other parts of the program code and shouldn't be completely ruled out but realistically I suspect the problem is one of the two former possible issues of either indentation or internal loop code itself, I have already tried multiple variations of 'indentation layout' as well as making quick fixes (misstyped syntax etc). The code in question can be found towards the end of the program code (there is only one 'while loop' in the program code) it is in the 'menu options' section of code under '# Loop through quotes selecting those referencing the appropriate month and store the data in the summary dictionary'. I have included two separate code windows, one highlighting the suspected 'problem code' and the the other with 'full program code'. Any help in any aspect will be appreciated. Code segment most likely to hold error def monthlyReport(): file = open(QUOTES_TO_DATE_FILE, 'r') text = file.read() file.close() quotes = text.split() month = input('Enter month: ') summary = {'Lawn':{'Quantity' : 0.0, 'Value' : 0.0}, 'Patio' :{'Quantity' : 0.0, 'Value' : 0.0}, 'Water Feature' :{'Quantity' : 0.0, 'Value' : 0.0}} # Loop through quotes selecting those referencing the appropriate month and #store the data in summary dictionary index = 0 while True: if quotes[index] == month: inputQuotesFromFile2(quotes[index+1]) summary['Lawn']['Quantity'] = summary['Lawn']['Quantity'] + quote['Lawn']['Width'] * quote['Lawn']['Length'] summary['Lawn']['Value'] = summary['Lawn']['Value'] + quote ['Lawn']['Cost'] summary['Patio']['Quantity'] = summary['Patio']['Quantity'] + quote['Patio']['Width'] * quote['Patio']['Length'] summary['Patio']['Value'] = summary['Patio']['Value'] + quote['Patio']['Cost'] summary['Water Feature']['Quantity'] = summary['Water Feature']['Quantity'] + quote['Water Feature']['Quantity'] summary['Water Feature']['Value'] = summary['Water Feature']['Value'] + quote['Water Feature']['Cost'] index = index + 2 if (index >= len(quotes)): break totalValue = summary['Lawn']['Value'] + summary['Patio']['Value'] + summary['Water Feature']['Value'] outputSummaryDictionary(summary, month, totalValue) Full program code # `Dictionary containing time values (mins) per square metre/ per feature ##lawn:20 patio:20 water feature:60 TIME = {'Lawn': 20, 'Patio': 20, 'Water Feature': 60} # Constant for labour cost ##16.49 LABOUR_COST = 16.49 # Variable for filename of list of quotes made to date ##quotesToDateFile QUOTES_TO_DATE_FILE = 'quotesToDateFile.txt' # 'Global variables' # A dictionary that stores quote data temporarily, contains sub dicts for each #material type including keys for length, width, cost, time/quantity,cost, time quote = {'Lawn':{'Length': 0 , 'Width': 0 , 'Cost': 0.0 , 'Time': 0.0}, 'Patio':{'Length': 0 , 'Width': 0, 'Cost': 0.0 , 'Time': 0.0 }, 'Water Feature':{'Quantity': 0 , 'Cost': 0.0 , 'Time': 0.0}} # A dictionary storing material costs of individual items (can be updated) materialCost = {'Lawn': 15.5, 'Patio': 20.99, 'Water Feature': 150} # 'Input' # Function to input material info defined by a length ##create function with named parameter for 'item' def inputItemDimensions(item): s = 'Enter length of ' + item + ':' length = int(input('Enter length of material: ')) s = 'Enter width of ' + item + ':' width = int(input('Enter width of material: ')) return length, width # Function to input material info defined by quantity ##create function with named parameter 'item def inputItemQuantity(item): s = 'Enter quantity of ' + item + ':' quantity = int(input('Enter quantity of items: ')) return quantity # Function for input of area and quantity def itemInput(): global quote quote['Lawn']['Length'], quote['Lawn']['Width'] = inputItemDimensions('lawn') quote['Patio']['Length'], quote['Patio']['Width'] = inputItemDimensions('concrete patio') quote['Water Feature']['Quantity'] = inputItemQuantity('water feature') # 'Cost calculation' # Function to calculate, output to screen, return the material cost and time #to install a landscape item installed by length and width def costCalculation1(num, item, length, width, cost, time): print('[{0}]'.format(num)) print('Length and width of the {0} = {1} x {2}m'.format(item, length, width)) area = length * width print('Total area of {0} = {1:.2f}m^2'.format(item, area)) print('Cost of {0} per m^2 = £{1:.2f}'.format(item, cost)) totalCost = area * cost print('Total cost of {0} = £{1}\n'.format(item, totalCost)) totalTime = area * time return totalCost, totalTime # Function to calculate, output to screen and return the material cost and time #to install a landscape item installed by quantity def costCalculation2(num, item, quantity, cost, time): print('[{0}]'.format(num)) print('Quantity of {0} = {1} items'.format(item, quantity)) print('Cost of one {0} = £{1:.2f}'.format(item, cost)) totalCost = quantity * cost print("Total cost of {0} {1} = £{2}\n".format(quantity, item, totalCost)) totalTime = quantity * time return totalCost, totalTime # Function to calculate individual costs of items def calculateItemCosts(): global quote quote['Lawn']['Cost'], quote['Lawn']['Time'] = costCalculation1('1', 'lawn', quote['Lawn']['Length'], quote['Lawn']['Width'], materialCost['Lawn'], TIME['Lawn']) quote['Patio']['Cost'], quote['Patio']['Time'] = costCalculation1('2', 'patio', quote['Patio']['Length'], quote['Patio']['Width'], materialCost['Patio'], TIME['Patio']) quote['Water Feature']['Cost'], quote['Water Feature']['Time'] = costCalculation2('3', 'water features', quote['Water Feature']['Quantity'], materialCost['Water Feature'], TIME['Water Feature']) # Function to calculate workimg costs and output them def workingCost(): print('Working costs:') totalTime = (quote['Lawn']['Time'] + quote['Patio']['Time'] + quote['Water Feature']['Time']) / 60 labourCost = totalTime * LABOUR_COST print('Total time to complete work = {0} mins'.format(totalTime)) print('Cost of work per hour = £{0}'.format(LABOUR_COST)) print('Total cost of work = £{0}\n'.format(labourCost)) # Calculate total fee payable by customer, output to screen and file materialCost = quote['Lawn']['Cost'] + quote['Patio']['Cost'] + quote['Water Feature']['Cost'] totalCost = materialCost + labourCost print('Total cost to pay = £{0}\n'.format(totalCost)) # 'Output functions' # Output details concerning item def outputItems(): outputItems1('1', 'Lawn', quote['Lawn']) outputItems1('2', 'Patio', quote['Patio']) outputItems2('3', 'Water Feature', quote['Water Feature']) # Output dimensions and cost for certain item def outputItems1(num, item, itemDict): print('[{0}]'.format(num)) print('Length of width of {0} = {1}m x {2}m'.format(item, itemDict['Length'], itemDict['Width'])) print('Total cost of {0} = £{1}'.format(item, itemDict['Cost'])) print('Time to install {0} = {1}mins\n'.format(item, itemDict['Time'] / 60)) # Output quantity and cost for item def outputItems2(num, item, itemDict): print('[{0}]'.format(num)) print('Quantity of {0} = {1} items'.format(item, itemDict['Quantity'])) print('Cost of one {0} = £{1:.2f}'.format(item, itemDict['Cost'])) print('Time to install {0} = {1:.2f} hours\n'.format(item, itemDict['Time'] / 60)) # Output material cost dictionary def outputMaterialCostDictionary(): for key, value in materialCost.items(): print('{0} = {1}'.format(key, value)) print('\n') # Output summary dictionary def outputSummaryDictionary(summaryD, month, totalV): outputSummaryItem1(['Month', month, '', '', '']) outputSummaryItem1(['Total', '', 'Total', 'Total', 'Total']) outputSummaryItem1(['Working', 'Item', 'Square metre', 'Number', 'Monthly']) outputSummaryItem1(['Costs', '', 'Purchased', 'Purchased', 'Value']) outputSummaryItem2('Lawn', summaryD['Lawn']) outputSummaryItem2('Patio', summaryD['Patio']) outputSummaryItem3('Water Feature', summaryD['Water Feature']) outputSummaryItem4(totalV) # Output summary dictionary item ver 1 def outputSummaryItem1(sList): print('|{0:^13}|{1:^13}|{2:^13}|{3:^13}|{4:^13}|'.format(sList[0], sList[1], sList[2], sList[3], sList[4])) # Output summary dictionary item ver 2 def outputSummaryItem2(name, item): print('|{0:^13}|{1:^13}|{2:13.2f}|{3:^13}|{4:13.2f}|'.format('', name, item['Quantity'], '', item['Value'])) # Output summary dictionary item ver 3 def outputSummaryItem3(name, item): print('|{0:^13}|{1:^13}|{2:^13}|{3:13.0f}|{4:13.2f}|'.format('', name, '', item['Quantity'], item['Value'])) # Output summary dictionary item ver 4 def outputSummaryItem4(totalValue): print('|{0:^13}|{1:^13}|{2:^13}|{3:^13}|{4:13.2f}|'.format('Total', '', '', '', totalValue)) # 'File handling' # Function to output file def outputToFile(): filename = input('Enter file name: ') file = open(filename, 'w') month = input('Enter month:' ) print('Filename = {0}....Month = {1}\n'.format(filename, month)) file.write('{0}\n'.format(month)) s = '{0} {1} {2} {3}\n'.format(quote['Lawn']['Length'], quote['Lawn']['Width'], quote['Lawn']['Cost'], quote['Lawn']['Time']) file.write(s) s = '{0} {1} {2} {3}\n'.format(quote['Patio']['Length'], quote['Patio']['Width'], quote['Patio']['Cost'], quote['Patio']['Time']) file.write(s) s = '{0} {1} {2}\n'.format(quote['Water Feature']['Quantity'], quote['Water Feature']['Cost'], quote['Water Feature']['Time']) file.write(s) file.close() # Update quotes to date file file = open(QUOTES_TO_DATE_FILE, 'a') s = '{0} {1}\n'.format(month, filename) file.write(s) file.close() # Function to input quote from file where file name is not known def inputQuoteFromFile1(): filename = input('Enter name for input file: ') inputQuoteFromFile2(filename) # Function to input quote from file when file IS known def inputQuoteFromFile2(filename): file = open(filename, 'r') text = file.read() list1 = text.split() file.close() # Process the data (ignore first item which is the month) ##declare 'quote' dict as global (this might mean this code is within function) global quote subDictionary = {'Length' : float(list1[1]), 'Width' : float(list1[2]), 'Cost' : float(list1[3]), 'Time' : float(list1[4])} quote['Lawn'] = subDictionary subDictionary = {'Length' : float(list1[5]), 'Width' : float(list1[6]), 'Cost' : float(list1[7]), 'Time' : float(list1[8])} quote['Patio'] = subDictionary subDictionary = {'Quantity' : float(list1[9]), 'Cost' : float(list1[10]), 'Time' : float(list1[11])} quote['Water Feature'] = subDictionary file.close() # 'Menu options' # Function to allow preperation of a new quote def prepareANewQuote(): itemInput() calculateItemCosts() workingCost() outputToFile() # Function to load new material costs def loadNewMaterialCosts(): filename = input('Enter filename: ') file = open(filename, 'r') text = file.read() file.close() newMaterialCosts = text.split() # Assign costs to material cost dictionary index = 0 for key in materialCost.keys(): materialCost['Key'] = float(newMaterialCosts['index']) index = index + 1 # Output new material costs # NOTE MAY NEED TO BE INDENTED FURTHER outputMaterialCostDictionary() # Function to view and load existing quote def viewExistingQuote(): inputQuoteFromFile1() outputItems() workingCost() # Function to generate monthly report summary def monthlyReport(): file = open(QUOTES_TO_DATE_FILE, 'r') text = file.read() file.close() quotes = text.split() month = input('Enter month: ') summary = {'Lawn':{'Quantity' : 0.0, 'Value' : 0.0}, 'Patio' :{'Quantity' : 0.0, 'Value' : 0.0}, 'Water Feature' :{'Quantity' : 0.0, 'Value' : 0.0}} # Loop through quotes selecting those referencing the appropriate month and #store the data in summary dictionary index = 0 while True: if quotes[index] == month: inputQuotesFromFile2(quotes[index+1]) summary['Lawn']['Quantity'] = summary['Lawn']['Quantity'] + quote['Lawn']['Width'] * quote['Lawn']['Length'] summary['Lawn']['Value'] = summary['Lawn']['Value'] + quote ['Lawn']['Cost'] summary['Patio']['Quantity'] = summary['Patio']['Quantity'] + quote['Patio']['Width'] * quote['Patio']['Length'] summary['Patio']['Value'] = summary['Patio']['Value'] + quote['Patio']['Cost'] summary['Water Feature']['Quantity'] = summary['Water Feature']['Quantity'] + quote['Water Feature']['Quantity'] summary['Water Feature']['Value'] = summary['Water Feature']['Value'] + quote['Water Feature']['Cost'] index = index + 2 if (index >= len(quotes)): break totalValue = summary['Lawn']['Value'] + summary['Patio']['Value'] + summary['Water Feature']['Value'] outputSummaryDictionary(summary, month, totalValue) # 'Main' (initialisation) # Top level function def start(): while True : print('Select one of following options') print('(1) Prepare new quote') print('(2) Load new cost data') print('(3) Load and view existing quote') print('(4) Generate monthly report summary') print('(5) Exit') selection = int(input()) if selection == 1: prepareANewQuote() elif selection == 2: loadNewMaterialCosts() elif selection == 3: viewExistingQuote() elif selection == 4: monthlyReport() elif selection == 5: quit() else: print('Error unrecognised command') # Start start()
index never gets modified if quotes[index] does not equal month, so the code will keep checking the same value over and over again and never proceed. You should unindent that assignment of index by one level. But really this is not an appropriate use of a while loop; you should use for to iterate over quotes: for quote in quotes: (Also note there are two while loops in this code; and actually far too much use of global.)
How can I apply multiprocessing to this function?
I wrote a little script which scrapes a platform for job advertisments, everything working pretty fine but really slow, since im iterating through up to 200 advertisments for information. While I still think I could code some stuff better to make it run faster aswell, the fact that I couldnt get multiprocessing working here is what bothers me most. These are the functions, which do the main work, i was trying to add an intern function for the for loop in def get_all_job_details() to map it, but it would always throw an PicklingError or sometimes i got "Expected exactly 2 arguments 3 given" in open_file() which i cant understand tbh. def get_job_links(section_URL): soup = make_soup(section_URL) internerLink = soup.find_all("a", "internerLink primaerElement") job_links = [BASE_URL + link["href"] for link in internerLink] return job_links def get_all_job_links(section_URL): all_job_links = [] for page in range(1, PAGE_COUNT + 1): newURL = section_URL[:-1] + str(page) all_job_links.extend(get_job_links(newURL)) return all_job_links def get_job_details(job_URL): soup = make_soup(job_URL) details = {'job_URL': job_URL, 'refnr': '', 'firmName': '', 'fName': '', 'sName': '', 'adressStr': '', 'adressPlz': '', 'adressOrt': '', 'email': '', 'jobtype': '', 'gender': '', 'status': ''} [details.update({'refnr': refnr.text}) for refnr in soup.findAll(id=re.compile("referenznummer"))] [details.update({'firmName': firmName.text}) for firmName in soup.findAll(id=re.compile("ruckfragenundbewerbungenan_-2147483648"))] [details.update({'fName': fName.text + ' '}) for fName in soup.findAll(id=re.compile("vorname_-2147483648"))] [details.update({'sName': sName.text}) for sName in soup.findAll(id=re.compile("nachname_-2147483648"))] [details.update({'adressStr': adressStr.text}) for adressStr in soup.findAll(id=re.compile("ruckfragenUndBewerbungenAn.wert\['adresse'\]Strasse_-2147483648"))] [details.update({'adressPlz': adressPlz.text}) for adressPlz in soup.findAll(id=re.compile("ruckfragenUndBewerbungenAn.wert\['adresse'\]Plz_-2147483648"))] [details.update({'adressOrt': adressOrt.text}) for adressOrt in soup.findAll(id=re.compile("ruckfragenUndBewerbungenAn.wert\['adresse'\]Ort_-2147483648"))] [details.update({'email': str(email['href'])[7:]}) for email in soup.findAll(id=re.compile("vermittlung.stellenangeboteverwalten.detailszumstellenangebot.email"))] jobtype = soup.b if jobtype: jobtype = soup.b.text else: jobtype = '' if jobtype.find("Anwendungsentwicklung") > -1: details.update({'jobtype': u"Fachinformatiker für Anwendungsentwicklung"}) elif jobtype.find("Systemintegration") > -1: details.update({'jobtype': u"Fachinformatiker für Systemintegration"}) elif jobtype.find("Medieninformatik") > -1: details.update({'jobtype': u"Medieninformatiker"}) elif jobtype.find("Informatikkaufmann") > -1: details.update({'jobtype': u"Informatikkaufmann"}) elif jobtype.find("Systemkaufmann") > -1: details.update({'jobtype': u"IT-Systemkaufmann"}) else: details.update({'jobtype': u"Informatiker"}) soup.find("div", {"class": "ausklappBox"}).decompose() genderdiv = str(soup.div) gender = '' if genderdiv.find("Frau") > -1: gender += "Frau " if genderdiv.find("Herr") > -1: gender += "Herr " if len(gender) > 5: gender = '' details.update({'gender': gender}) return details def get_all_job_details(section_URL): all_job_details = [] all_job_links = get_all_job_links(section_URL) for i in range(len(all_job_links)): all_job_details.append(get_job_details(all_job_links[i])) printProgress(i, len(all_job_links) - 1, prefix='Progress:', suffix='Complete', barLength=50) return all_job_details def printProgress(iteration, total, prefix='', suffix='', decimals=2, barLength=100): """ Call in a loop to create terminal progress bar #params] = iteration - Required : current iteration (Int) total - Required : total iterations (Int) prefix - Optional : prefix string (Str) suffix - Optional : suffix string (Str) decimals - Optional : number of decimals in percent complete (Int) barLength - Optional : character length of bar (Int) """ filledLength = int(round(barLength * iteration / float(total))) percents = round(100.00 * (iteration / float(total)), decimals) bar = '#' * filledLength + '-' * (barLength - filledLength) Sys.stdout.write('%s [%s] %s%s %s\r' % (prefix, bar, percents, '%', suffix)), Sys.stdout.flush() if iteration == total: print("\n\n") So how do I do it correctly?