I have written this python program for a game:
print("CC ACTIVATED")
import lcddriver
import time
import subprocess
display = lcddriver.lcd()
try:
display.lcd_display_string("CC... ", 1)
time.sleep(2)
display.lcd_display_string("ONLINE", 2)
time.sleep(2)
display.lcd_clear()
except Exception:
print("SCREEN ERROR")
try:
display.lcd_display_string("SETUP A", 1)
display.lcd_display_string("PASSWORD? Y/N", 2)
except Exception:
print("SCREEN ERROR")
activate = input("")
if activate == 'y':
print("ACTIVATED")
try:
display.lcd_clear()
display.lcd_display_string("", 1)
time.sleep(2)
display.lcd_display_string("LOADING", 2)
time.sleep(2)
display.lcd_clear()
except Exception:
print("SCREEN ERROR")
else:
print("ABORT")
try:
display.lcd_clear()
display.lcd_display_string("", 1)
time.sleep(2)
display.lcd_display_string("ABORT", 2)
time.sleep(2)
display.lcd_clear()
subprocess.call(["sudo","halt"])
except Exception:
print("SCREEN ERROR")
subprocess.call(["sudo","halt"])
k = True
while k:
try:
display.lcd_clear()
display.lcd_display_string("ENTER PASWORD", 1)
display.lcd_display_string("----------------", 2)
except Exception:
print("SCREEN ERROR")
pasword = input("")
display.lcd_clear()
try:
display.lcd_clear()
display.lcd_display_string("YOU TYPED:", 1)
display.lcd_display_string(pasword, 2)
time.sleep(2)
display.lcd_display_string("CONFIRM? Y/N", 1)
except Exception:
print("SCREEN ERROR")
ok = input("")
if ok == 'y':
k = False
else:
display.lcd_clear()
try:
display.lcd_clear()
display.lcd_display_string("PASSWORD", 1)
display.lcd_display_string("SET", 2)
except Exception:
print("SCREEN ERROR")
time.sleep(2)
run = True
try:
display.lcd_clear()
display.lcd_display_string("STARTING ", 1)
display.lcd_display_string("GAME...", 2)
except Exception:
print("SCREEN ERROR")
time.sleep(2)
while run:
try:
display.lcd_clear()
display.lcd_display_string("ENTER PASSWORD ", 1)
display.lcd_display_string("TO DEACTIVATE", 2)
except Exception:
print("SCREEN ERROR")
pasword1 = input("")
if pasword1 == pasword:
try:
display.lcd_clear()
display.lcd_display_string("PASSWORD....", 1)
time.sleep(2)
display.lcd_display_string("ACCEPTED", 2)
time.sleep(2)
display.lcd_clear()
display.lcd_display_string("DEACTIVATED", 2)
subprocess.call(["sudo","halt"])
time.sleep(10)
except Exception:
print("SCREEN ERROR")
subprocess.call(["sudo","halt"])
else:
try:
display.lcd_clear()
display.lcd_display_string("PASSWORD....", 1)
time.sleep(2)
display.lcd_display_string("UNACCEPTED", 2)
time.sleep(2)
except Exception:
print("SCREEN ERROR")
It runs on a raspberry pi and works absolutely fine, but there is one thing I want to do that is a bit above my skill level. I need this program to give you three attempts to guess the password,then at the fourth attempt play an audio recording. Afterward it needs to respond to failed attempts with the audio recording for five minutes and then go back to the silent three chances. I know how to get it to do the audio recording, but I need help with the five minute part. Does anyone here know how to do this? Thanks.
To permit three password attempts, you will need a counter variable which will count up to three with each failed attempt.
Rather than just running while k == True, you want to check against both k == True and attempts <= 3. As far as waiting five minutes, you will want to create a timestamp of when the user last guessed.
from datetime import datetime
...
k = True
password_attempts = 0
while k and password_attempts < 4:
try:
display.lcd_clear()
display.lcd_display_string("ENTER PASWORD", 1)
display.lcd_display_string("----------------", 2)
except Exception:
print("SCREEN ERROR")
pasword = input("")
display.lcd_clear()
try:
display.lcd_clear()
display.lcd_display_string("YOU TYPED:", 1)
display.lcd_display_string(pasword, 2)
time.sleep(2)
display.lcd_display_string("CONFIRM? Y/N", 1)
except Exception:
print("SCREEN ERROR")
ok = input("")
if ok == "y":
k = False
else:
display.lcd_clear()
password_attempts += 1
if password_attempts == 4:
#Create a timestamp of last attempt
last_request = datetime.now()
current_request = datetime.now()
while((last_request - current_request).total_seconds() < 5 * 60):
#Code to play music
current_request = datetime.now()
Then it's up to you to re-route the player back to the point in the program where they try entering the passwords again.
But, the design choices you've made at the beginning of this project will really start to get in the way of what you want to do.
I suggest you consider a redesign of your program, in order to make working on it much easier and more pleasant.
One of the best parts of programming is code re-use; this is most easily understood with functions. In Python, you create a function with the syntax def function_name():
Then, when you want to run the code within that function, you simply call it by name: function_name().
What does this mean for your app?
You could wrap writing to the LCD in a method, so that you can avoid repeatedly typing out the same try:... except: block (by the way... when you write except Exception, you are catching ALL exceptions your program might throw. This is considered bad practice, because you may not want to do the same thing irrespective of what the exception was in the first place. Rather, try to find a specific exception you're trying to catch, and catch that one by name, specifically).
An example of rewriting the LCD printing:
def print_to_lcd(statements_to_print: [str]):
line_number = 1
try:
for statement in statements_to_print:
display.lcd_display_string(statement, line_number)
line_number += 1
except Exception:
print("SCREEN ERROR")
Then, you just produce a list of things for the LCD to print, and call the LCD function with them:
things_to_write = ["PASSWORD...", "UNACCEPTED"]
print_to_lcd(things_to_write)
The same can be said about how you check your password value, when you play the music, etc.
Any time you find yourself repeatedly re-writing the same information, take a moment and think if there's a way you can write it once, and just re-use it. It'll make your programs much easier to write, and much easier to use.
Particularly in this case, since you want to re-do the same thing after waiting for a period of time. Imagine, rather than having to write tons of if-statements, when the user enters the password wrong for the fourth time, you just write something like:
play_music_for_five_minutes()
prompt_for_password()
Let me know if there are any further questions I can answer!
Related
The code I have works. The last for loop gets reached and choice.click() gets clicked on. The question I have is why the except block gets executed even though the:
if choice.text == call_resource:
choice.click()
break
piece of the code is reached and the choice.click() portion works?
def select_choice(driver, resource_tag):
try:
call_resource = None
access_data = common.retrieve_tag_access_data()
for row in access_data["access_data"]:
if str(row["id"]) == resource_tag:
call_resource = row["row_tag"]["name"]
break
if call_resource is None:
access_data = common.retrieve_fixture_access_data()
for row in access_data["access_data"]:
if str(row["id"]) == resource_tag:
call_resource = row["row_tag"]["name"]
break
menu = driver.find_element_by_css_selector("ul[role='listgrid']")
choices = menu.find_elements_by_css_selector("li[role='choices']")
for choice in choices:
if choice.text == call_resource:
choice.click()
break
except:
error(logger, "unable to select choice")
pass
Because the last for loop works, shouldn't it break entirely out of the function after choice.click() without executing the except: portion of the code?
The except: portion will run only if an Exception occurred inside the try block. You should change the except: line to something like except Exception as e: and print the variable e in some way so you can discover what the problem is.
choices = menu.find_elements_by_css_selector("li[role='choices']")
for choice in choices:
if choice.text == call_resource:
choice.click()
break
Could be replaced with since your only trying to click one element with a certain text why not just try to find it. If it errors out it will go to the exception you provided.
driver.find_element(By.XPATH,f"//li[#role='choices' and contains(text(),{call_resource})]").click()
Also use to find errors use the following.
except Exception as e:
print(str(e))
The program isn't printing what I want ("too slow") after the except with the KeyboardInterrupt, which should end the program and print the string, instead the program just ends. I tried messing around with it a bit but can't seem to figure it out. What should I do?
import os
import signal
import threading
from random import randint
def timed_input(interval, *args):
t = threading.Timer(interval, os.kill, args=(os.getpid(), signal.SIGINT))
t.start()
try:
return int(input(*args))
except:
pass
finally:
t.cancel()
while True:
want = randint(1,9)
try:
got = timed_input(5, f'type "{want}": ')
except KeyboardInterrupt:
print('too slow')
else:
if got != want:
print('You Lose.')
break
This is because your first function is removing the KeyboardInterrupt thus making the second try block useless.
To fix this add another except block for the first function so it is properly raised:
import os
import signal
import threading
from random import randint
def timed_input(interval, *args):
t = threading.Timer(interval, os.kill, args=(os.getpid(), signal.SIGINT))
t.start()
try:
return int(input(*args))
except KeyboardInterrupt:
raise
except ValueError:
pass
finally:
t.cancel()
while True:
want = randint(1,9)
try:
got = timed_input(5, f'type "{want}": ')
except KeyboardInterrupt:
print('too slow')
else:
if got != want:
print('You Lose.')
break
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...")
Is there any way to enter try statement once again after catching the exception in the first try?
Now I'm using "while" and "if" statements and it is making the code messy.
Any ideas?
Will try to simplify it as possible, sorry that have no logic...
run = True
tryAgain = True
a=0
while run:
try:
2/a
except Exception:
if tryAgain:
tryAgain = False
a = 1
else:
run = False
You could try using a break statement in your try block:
while True:
try:
# try code
break # quit the loop if successful
except:
# error handling
Considering you are doing this in a while, then you can make use of continue to just continue back to the beginning of the while loop:
tryAgain = True
a=0
while True:
try:
2/a
break # if it worked then just break out of the loop
except Exception:
if tryAgain:
continue
else:
# whatever extra logic you nee to do here
I like using a for loop so that the trying and trying doesn't go on forever. Then the loop's else clause is a place to put the "I give up" code. Here is a general form that will support 'n' retries > 1:
a=0
num_tries = 5
for try_ in range(0,num_tries):
try:
2/a
except Exception:
print("failed, but we can try %d more time(s)" % (num_tries - try_ - 1))
if try_ == num_tries-2:
a = 1
else:
print("YESS!!! Success...")
break
else:
# if we got here, then never reached 'break' statement
print("tried and tried, but never succeeded")
prints:
failed, but we can try 4 more time(s)
failed, but we can try 3 more time(s)
failed, but we can try 2 more time(s)
failed, but we can try 1 more time(s)
YESS!!! Success...
I'm new to Python, so this may not be best practice. I returned to the try statement after triggering the exception by lumping everything into a single function, then recalling that function in the except statement.
def attempts():
while True:
try:
some code
break #breaks the loop when sucessful
except ValueError:
attempts() #recalls this function, starting back at the try statement
break
attempts()
Hope this addresses your question.
I'm using the eval method in my project and I have to handle all the possible exceptions it may raise. I thought that simple try and except would work but when I enter a symbol it doesn't familiar with it stuck.. like eval("5:2").
try:
max = abs(eval(game_function))
except:
while True:
x += (x_f_coordinate - x_0_coordinate) / 1050
try:
max = abs(eval(game_function))
break
except KeyboardInterrupt:
raise
except:
if x < x_f_coordinate:
continue
It's freezing in the 7th line.
Any suggestions?