I have written a program in python which is supposed to return the highest scoring player for each level, however it keeps returning "KeyError: 20" for line 69 ( P_L1=players_TS[H_L1] ), and I can't work out how to fix this. In my code I open a text file called "playerScores.txt" which is formatted like this:
Moon,3,15
StarPlayer,2,18
Ellie,5,9
etc.
Here is my code:
print("The highest scorers for each leve are:\n")
PS3=open("PlayerScores.txt","r").read().split("\n")
level1_scores=[]
players_TS={}
level2_scores=[]
players_T2={}
level3_scores=[]
players_T3={}
level4_scores=[]
players_T4={}
level5_scores=[]
players_T5={}
for line in PS3:
lines=line.split(",")
player=lines[0]
level=lines[1]
score=lines[2]
erros=open("scoreboard_errorlog.text","w")
if int(score)>20:
errors.write(score)
if int(level)>5:
errors.write(level)
if int(level)==1:
level1_scores.append(int(score))
players_TS.setdefault(score,[]).append(player)
if int(level)==2:
level2_scores.append(int(score))
players_T2.setdefault(score,[]).append(player)
if int(level)==3:
level3_scores.append(int(score))
players_T3.setdefault(score,[]).append(player)
if int(level)==4:
level4_scores.append(int(score))
players_T4.setdefault(score,[]).append(player)
if int(level)==5:
level5_scores.append(int(score))
players_T5.setdefault(score,[]).append(player)
H_L1=max(level1_scores)
P_L1=players_TS[H_L1]
H_L2=max(level2_scores)
P_L2=players_T2[H_L2]
H_L3=max(level3_scores)
P_L3=players_T3[H_L3]
H_L4=max(level4_scores)
P_L4=players_T4[H_L4]
H_L5=max(level5_scores)
P_L5=players_T5[H_L5]
print("Level\tPlayer name\tScore\nLevel 1\t",P_L1,"\t",H_L1,"\nLevel 2\t",P_L2,"\t",H_L2,"\nLevel 3\t",P_L3,"\t",H_L3,"\nLevel 4\t",P_L4,"\t",H_L4,"\nLevel 5\t",P_L5,"\t",H_L5)
Help will be much appreciated.
The problem arises here:
if int(level)==1:
level1_scores.append(int(score))
players_TS.setdefault(score,[]).append(player)
Suppose score == "20"
. You are adding the integer 20
to level1_scores
, but using the string "20"
as a key in players_TS
. Then, when you get to these lines
H_L1=max(level1_scores)
P_L1=players_TS[H_L1]
H_L1
is the integer value 20
, but all the keys in players_TS
are strings like "20"
. Since 20 != "20"
, a KeyError
results.
Likely, you want to have score
(and level
, for that matter) be an integer throughout, so convert it once immediately after you parse it, then use score
as is in the remainder of the loop.
for line in PS3:
lines = line.split(",")
player = lines[0]
level = int(lines[1])
score = int(lines[2])
with open("scoreboard_errorlog.text","w") as errors:
if score > 20:
errors.write(score)
if level > 5:
errors.write(level)
if level == 1:
level1_scores.append(score)
players_TS.setdefault(score,[]).append(player)
elif level == 2:
level2_scores.append(score)
players_T2.setdefault(score,[]).append(player)
elif level == 3:
level3_scores.append(score)
players_T3.setdefault(score,[]).append(player)
elif level == 4:
level4_scores.append(score)
players_T4.setdefault(score,[]).append(player)
elif level == 5:
level5_scores.append(score)
players_T5.setdefault(score,[]).append(player)
H_L1 = max(level1_scores)
P_L1 = players_TS[H_L1]
H_L2 = max(level2_scores)
P_L2 = players_T2[H_L2]
H_L3 = max(level3_scores)
P_L3 = players_T3[H_L3]
H_L4 = max(level4_scores)
P_L4 = players_T4[H_L4]
H_L5 = max(level5_scores)
P_L5 = players_T5[H_L5]
However, you should also be using dict
s to store a lot of this data, rather than individually named variables.
level_scores = {level: [] for level in range(1,6)}
players = {}
for line in PS3:
lines = line.split(",")
player = lines[0]
level = int(lines[1])
score = int(lines[2])
# Use append mode, or you overwrite the file each time through the loop
with open("scoreboard_errorlog.text", "a") as errors:
if score > 20:
errors.write(score)
if level > 5:
errors.write(level)
continue
level_scores[level].append(score)
players[level].setdefault(score,[]).append(player)
H = {}
P = {}
for level in range(1,6):
H[level] = max(level_scores[level])
P[level] = players[level][H[level]]