So, I was doing an online course for python, and there was a test sample code for the "Guess The Movie", game. However, I tried to write it myself following almost the same logic but there seems to be an error where multiple letters are being unlocked rather than only one.
for Example:
ROB , your turn
Your letter:o
o * l
As you can see instead of showing that only the letter 'o' is unlocked, the last letter 'l' is also unlocked even though i have not entered it previously.the movie here is called 'Soul'.
and upon entering the letter 'S' it shows:
Press 1 to guess the movie or 2 to unlock another character 2
Your letter:S
S o u l
The movie is completely unlocked.If you can find the mistake in my code, please give me a solution.
My Code:
import random
Films=["Deadpool","Avengers Endgame","Drishyam","Hera Pheri","Munna Bhai MBBS","Justice League","The Dark Knight","Cars","Titanic","Haseena Man Jayegi","Uri Surgical Strike","Guardians of the Galaxy","Interstellar","Inception","The Great Gatsby","John Wick","Spiderman Homecoming","Bajirao Mastani","Nobody","Life of Pi","Krish","Golmaal","Housefull","Zindagi Na Milegi Dobara","3 idiots","Dangal","Badshah","The Shawshank Redemption","Frozen","Soul","Despicable Me","Minions","Crossroads"]
def create_question(Movie):
n=len(Movie)
letters=list(Movie)
temp=[]
for i in range(n):
if letters[i]== " ":
temp.append(" ")
else:
temp.append("*")
Q =" ".join(str(x) for x in temp)
return Q
def is_present(letter,Movie):
c=Movie.count(letter)
if c==0:
return False
else:
return True
def unlock(Q,picked_Movie,letter):
ref=list(picked_Movie)
Q_list=list(Q)
temp=[]
n=len(picked_Movie)
for i in range(n):
if ref[i]==" " or ref[i]==letter:
temp.append(ref[i])
else:
if Q_list[i]=="*":
temp.append("*")
else:
temp.append(ref[i])
Q_new =" ".join(str(x) for x in temp)
return Q_new
def game():
pA=input("Player 1 Name:")
pB=input("Player 2 Name:")
pp1=0
pp2=0
turn=0
willing=True
while willing:
if turn%2==0:
print(pA,",your turn")
picked_Movie=random.choice(Films)
Q=create_question(picked_Movie)
print(Q)
modified_Q=Q
not_said=True
while not_said:
letter=input("Your letter:")
if(is_present(letter,picked_Movie)):
modified_Q = unlock(modified_Q,picked_Movie,letter)
print(modified_Q)
d=int(input("Press 1 to guess the movie or 2 to unlock another character"))
if d==1:
ans=input("Answer:")
if ans==picked_Movie:
print("Yay! Correct answer.")
pp1=pp1+1
print(pA,"'s Score=",pp1)
not_said=False
else:
print("Wrong Answer, Try again...")
else:
print(letter,'not found')
c=int(input("press 1 to continue or 0 to exit:"))
if c==0:
print(pA,",Your Score is",pp1)
print(pB,",Your Score is",pp2)
print("Thank you for playing, have a nice day!!!")
willing=False
else:
print(pB,",your turn")
picked_Movie=random.choice(Films)
Q=create_question(picked_Movie)
print(Q)
modified_Q=Q
not_said=True
while not_said:
letter=input("Your letter:")
if(is_present(letter,picked_Movie)):
modified_Q = unlock(modified_Q,picked_Movie,letter)
print(modified_Q)
d=int(input("Press 1 to guess the movie or 2 to unlock another character:"))
if d==1:
ans=input("Answer:")
if ans==picked_Movie:
print("Yay! Correct answer.")
pp2=pp2+1
print(pB,"'s Score=",pp2)
not_said=False
else:
print("Wrong Answer, Try again...")
else:
print(letter,'not found')
c=int(input("press 1 to continue or 0 to exit:"))
if c==0:
print(pA,",Your Score is",pp1)
print(pB,",Your Score is",pp2)
print("Thank you for playing, have a nice day!!!")
willing=False
turn=turn+1
game()
I just changed unlock() method as below (changes are mentioned as comment):
def unlock(Q,picked_Movie,letter):
ref=list(picked_Movie)
Q_list=list(Q)
temp=[]
n=len(picked_Movie)
for i in range(n):
if ref[i]==" " or ref[i]==letter:
temp.append(ref[i])
else:
if Q_list[i]=="*" or Q_list[i] == " ": #Added 1 more condition Q_list[i] == " "
temp.append("*")
else:
temp.append(ref[i])
Q_new ="".join(str(x) for x in temp) #Replaced " " to ""
return Q_new
After a few times I run your code, tested it, I found the problem:
Inside unlock function, you did a mistake:
for i in range(n):
if ref[i]==" " or ref[i]==letter:
temp.append(ref[i])
else:
if Q_list[i]=="*":
temp.append("*")
else:
temp.append(ref[i])
You only checked if the Q_list[i] has *. But what if it has " " in it? Then you will get another letter from ref[i] for no reason!
The only thing you need to do is to modify the if statement:
for i in range(n):
if ref[i]==" " or ref[i]==letter:
temp.append(ref[i])
else:
if Q_list[i]=="*" or Q_list[i] == " ": # <-- FIX HERE
temp.append("*")
else:
temp.append(ref[i])
EDIT:
I saw that in some cases my code still doesn't work, and this is why:
If the movie name had " " in it, then the
Q_list will be bigger then ref which will give us unexpected results.
You can fix it easily, removing all the " " between the *.
Everywhere you have:
" ".join(str(x) for x in temp)
this in your code (twice actually), changes it to:
"".join(str(x) for x in temp)
I use a python script to update ~500 Google Sheets (using some wrappers on the google api) every morning, and find that I need to catch API errors all the time. I wanted to write a generic "try this function, catch any errors" function, and was able to pass in the function and its parameters successfully, but it doesn't seem to catch the errors. Only if I wrap the original function call in a try/catch does it actually handle the error. This works, but it's starting to feel like half of my code is try/catch protocol.
Should this be working? Is there something different I can do so I only need to write my "try protocols" once?
My attempt at a generic catch function:
def try_function(function, teacher_name="teacher", note="unknown when", tab=None):
check = True
count = 0
while check:
check = False
try:
function
except Exception as e:
if str(e).find("Quota exceeded")>-1:
print("API Quota exceeded " + note + ", waiting 100 seconds - " + teacher_name)
time.sleep(100)
check = True
count+=1
elif str(e).find("The service is currently unavailable")>-1:
print("API threw 'currently unavailable error' " + note + ", waiting 100 seconds - " + teacher_name)
time.sleep(100)
check = True
count+=1
elif str(e).find("Read timed out.")>-1:
print("API threw 'Read timed out.' error " + note + ", waiting 150 seconds - " + teacher_name)
time.sleep(150)
check = True
count+=1
elif str(e).find("Internal error encountered.")>-1:
print("API threw 'Internal error encountered' " + note + ", waiting 100 seconds - " + teacher_name)
time.sleep(100)
check = True
count+=1
else:
print("Non-quota error " + note + ", teacher may not have been updated, waiting 250s - " + teacher_name)
print(e)
time.sleep(250)
del spread
continue
if count > 4:
print("Tried this 5 times, ending try loop - " + teacher_name)
del spread
continue
Called like this: try_function(spread.df_to_sheet(parameters), "name", "note")
Do I have to wrap that last line in order to actually catch an error?
You need to actually call the function inside your try block, and the thing you pass in has to be an actual function (not the result of already having called a function). Simplifying down the exception handling into a generic retry for the sake of making the example simpler (note that in real life you would typically handle different types of exceptions by matching on the type of the exception rather than trying to parse its string representation), it would look like this:
def try_function(function, teacher_name="teacher", note="unknown when"):
count = 0
while True:
try:
function()
return
except Exception as e:
print(f"Error: {e} ({note}), waiting 100s and retrying...")
count += 1
time.sleep(100)
if count > 4:
print(f"Tried this 5 times, ending try loop - {teacher_name}")
return
try_function(lambda: spread.df_to_sheet(parameters), "name", "note")
Note that the lambda expression creates a function with no arguments that will invoke spread.df_to_sheet when it's called (which will happen inside your try block). This is the same as writing:
def to_sheet_fn():
spread.df_to_sheet(parameters)
try_function(to_sheet_fn, "name", "note")
I have a function which sends a request to a server. But sometimes the server doesn't reply and my code doesn't seem to continue. Now I wanted to implement, that the code continues to run, if no reply is received after a given amount of time. Below the code:
for attempt in range (3):
try:
print('Attempt: ' + str(attempt+1))
print('DUT: ' + str(x))
time.sleep(1)
response = request("http://" + ipEntry.get() + port, "temperature_test", x)
time.sleep(1)
print(response.text)
print(response.data.result)
answer = response.data.result
logFile.write(time.strftime("%Y_%m_%d-%H_%M_%S\t\t") + str(x) + "\t\t" + str(answer) + "\t\t" + str(readVoltage()) + "\t\t" + str(readCurrent()) + "\n")
except:
print('An error occured!')
else:
if (response.data.result==False):
print("Attempt " + str(attempt + 1) + " failed!")
else:
break
else:
print('All 3 attempts failed')
Is it possible to start a counter after the beginning of this function and check with an "if" statement if it has elapsed?
Thanks for any hints and best regards!
I am trying to access a variable within a function in a class and print it. Whenever I try I keep getting the error: AttributeError: 'NoneType' object has no attribute 'job_ID'.
def driver():
q = my_queue.Queue_()
for line in df:
if 'received' in line:
q.enqueue(line)
print("Adding job " + q.new_item.job_ID + " to the queue with the timestamp: " + q.new_item.time_stamp + ".")
print("The prority of the job is: " + q.new_item.job_priority)
print("The job type is: " + q.new_item.job_type)
if 'respond' in line:
q.dequeue()
print("Completed job " + q.current.job_ID + " in " + str(int(q.time_elapsed)) + " seconds.")
if 'active' in line:
q.active_jobs()
print("Total number of jobs: " + str(len(q.temp)))
print("Average priority: " + str(q.average))
if 'modify' in line:
q.modify(line)
print("Modified job " + q.current.job_ID)
The error is coming from the last print statement in this code.
This is the function within the class that is being used here:
def modify(self, x): # need to fix printing bug
self.current = self.head
while self.current != None:
if x[1] in self.current.get_data():
self.current.data[2] = x[2]
self.current.data[3] = x[3]
break
# print("Modified job " + current.job_ID)
else:
# print('The job details cannot be modified.')
pass
self.current = self.current.get_next()
The exit condition for the loop in the modify function that you have provided is self.current == None.
When you call modify() in this last conditional statement:
if 'modify' in line:
q.modify(line) // here
print("Modified job " + q.current.job_ID)
You are making q.current evaluate to None. Therefore, the reason why you are getting an AttributeError is because q.current is None, which has no such attribute called job_ID.
To fix your problem, you must ensure that q.current is not None before printing q.current.job_ID. I can't give you any help beyond this, since I don't know what the purpose of your program is.
I'm trying to get input from user, until he press ctrl-c. yet, I can't catch the
error, I think it has something to do with sklearn (I imported it for the rest of the code)
this is the code:
try:
while(True):
i+=1
put = input("\tEnter name of feature number " + str(i) +":\t")
features.append(put)
except KeyboardInterrupt:
print("\n\tFeatures Added!")
sleep(SLEEP)
return None
except:
exit("\nError has occurred, please come back later...")`
Fix your indentation as the following:
try:
while(True):
i+=1
put = input("\tEnter name of feature number " + str(i) +":\t")
features.append(put)
except KeyboardInterrupt:
print("\n\tFeatures Added!")
sleep(SLEEP)
return None
except:
exit("\nError has occurred, please come back later...")