Unreachable code in if statement inside a while loop - python-3.x

I was trying to make a menu with a while loop to keep repeating until a valid input was entered. This is the code that I have:
print("1) Play game")
print("")
print("2) Instructions")
print("")
print("3) Quit")
print("")
while True:
try:
menu = int(input("Make a selection: "))
except ValueError:
print("Sorry, your input was not valid")
continue
if menu > 3 or menu < 1:
print("Please use a number in the range 1-3")
continue
else:
break
if menu == 1:
print("Lets go!")
elif menu == 2:
print("Lets go!")
else:
print("Quitting...")
The "if" where it says "if menu > 3 or menu < 1:" gives an error saying that:
"Unreachable codepylint(unreachable)"
Please help, it would be much appreciated.

Problem 1: continue statement
To help you understand your code, i used a flowchart to draw the lines for you.
However, if you move the continue inside the except statement, then the code will pass onto the if statement on a successful try statement.
The challenge is, that the code is never going into the if menu > 3.... statement, it always goes to try or except and then does the continue. So its looping itself skipping the if menu > 3 .... statement. That means, you never get out of the loop as it never gets to execute break.
Problem 2: You said you removed the continue statement.
When you remove continue from the statement, you create a new problem. If the code goes into except clause, variable menu did not get created properly. So when it goes to if menu > 3 ..., the variable has not been defined (due to except clause), and that gives you a new error.
Solution:
I would recommend to move the continue statement inside the except clause. That will take care of the problem. It will go back to while statement if there is an error with the input for menu. If it is successful, then your if menu > 3 ... will execute properly.
The modified correct code will be:
while True:
try:
menu = int(input("Make a selection: "))
except ValueError:
print("Sorry, your input was not valid")
continue #move this inside except
if menu > 3 or menu < 1:
print("Please use a number in the range 1-3")
continue
else:
break
if menu == 1:
print("Lets go!")
elif menu == 2:
print("Lets go!")
else:
print("Quitting...")

Related

Do I need to look for a key down and up event to avoid double occurrence of my else block?

Wondering why its printing my else statement twice in this scenario. In theory it should just execute it once after an incorrect key is read, and loop back.
the out put I am getting after pressing a non 'enter' key How can I avoid this?
import random
import keyboard
#Constant values to assign as a win or loss
_WIN = 1
_LOSE = 0
#Create and store game hand choices
handChoice = ['Spock', 'Lizard', 'Rock', 'Paper', 'Scissors']
print('\nThis is advanced Rock, Paper, Scissors! Press ENTER to start the automated game->')
while True:
if keyboard.read_key() == 'enter':
break
else:
print('Please press ENTER!')
#Hand choices randomly assigned to player 1
player1 = random.choice(handChoice)
print('Player 1 uses ' + player1 + '!\n')
Looking true the docs you could use this:
keyboard.wait('enter')
It will also use less cpu. But you would need the async library with timeout to also give output.
you could also use this:
while True:
if keyboard.read_key() == 'enter':
break
elif event.event_type == keyboard.KEY_DOWN:
print('Please press ENTER!')

My code isn't running after I break a while loop even though there is code after it

I tried making a rock-paper-scissors game, and to make sure that the user entered a number, I made a while loop. But after the user entered a number, the loop breaks but it won't keep running the game itself after it. How do I fix this?
main_choice = input('Please enter the number that matches your choice:\n')
#Make sure that user enters a number
while True:
try:
int(main_choice)
break
except:
main_choice = input('Please enter a NUMBER:\n')
continue
#Play
if main_choice == 1:
play_game()
I see others have placed the answer in the comments... but I'll place the full example in here. You need to convert your input into an integer to be able to compare it (or the 1 into a str).
The line that needs to change:
if main_choice == 1:
Change to:
if int(main_choice) == 1:
main_choice = input('Please enter the number that matches your choice:\n')
#Make sure that user enters a number
while True:
try:
int(main_choice)
break
except:
main_choice = input('Please enter a NUMBER:\n')
continue
#Play
if int(main_choice) == 1:
print("Game is now being played")
Gives the output:
Please enter the number that matches your choice:
1
Game is now being played

NameError: free variable 'addcontact' referenced before assignment in enclosing scope

please be kind with my n00b question but it is driving me crazy and googling it didn't help much unfortunately.
I am trying to write a simple phonebook script using an empty dictionary as a learning exercise but as I am self taught there is no one else to turn to.
So here's what's happening,
I want to write a menu function that includes subfunctions for adding, deleting and editing {name:number} contacts
it is mostly working except for when I try to call the add function from within the edit
this is part of the menu code including the add routine
def menu():
selection = (int(input("""1:View phonebook
2:Add contact
3:Delete contact
4:Search for a contact and if necessary edit it
5:Save and Exit
What would you like to to?""")))
if selection == 1:
if len(phonebook)== 0:
print("Phonebook is empty, please add a contact first.")
loop = input("Press Enter to continue ...")
menu()
else:
print(phonebook)
loop = input("Press Enter to continue ...")
menu()
elif selection == 2:
def addcontact():
first = (str(input("First name: ")))
last = (str(input("Last name: ")))
num = (str(input("Number? ")))
phonebook.update({last + " " + first: num})
loop = input("Contact saved, press Enter to continue.")
menu()
(other stuff...)
menu()
and this is the update subroutine that's giving me trouble
elif selection == 4:
def search_and_edit():
search = (str(input("Please type the exact name of the contact you are looking for: ")))
if search in phonebook.keys():
print("Name: ", search, "Number: ", phonebook[search])
edit = (str(input("Do you wish to edit this contact? Y/N")))
if edit == "N" or edit == "n":
menu()
if edit == "Y" or edit == "y":
phonebook.pop(search)
addcontact()
else:
print("Contact not found.")
loop = input("Press Enter to continue.")
menu()
and this is the error message from PyCharm
File "C:\Users\Derek\PycharmProjects\pythonProject\phonebook\phonebook.py", line 78, in search_and_edit
addcontact()
NameError: free variable 'addcontact' referenced before assignment in enclosing scope
Process finished with exit code 1
what am I doing wrong here? the other callbacks work fine ("loop" callbacks to return to the main menu for example) but the addcontact() one fails with a variable error message even though it's a function
welcome aboard. The issue boils down to the addcontact being defined within the scope of a conditional (if...elif...else) and as a result not visible to search_and_edit which is defined in a different and mutually exclusive branch. So, when you chose 4, the program hadn't really entered 2 and the addcontact had not been "created" yet.
If you wish to make a function available at multiple places, then define it where it would in scope for all the callers.

Instagram bot not going to the next image

I have made an Instagram bot about 1 year ago.
From time to time Instagram has changed the code structure but I have always managed to successfully modify it in order to work.
Since a couple of weeks ago, Instagram has changed drastically.
I have made some changes but I will skip the Following part for the moment.
Currently I am facing some issues on selecting the next image after liking one.
for hashtag in hashtag_list:
tag += 1
webdriver.get('https://www.instagram.com/explore/tags/'+ hashtag_list[tag] + '/')
sleep(5)
first_thumbnail = webdriver.find_element_by_xpath('//*[#id="react-root"]/section/main/article/div[1]/div/div/div[1]/div[1]/a/div')
first_thumbnail.click()
sleep(randint(10,15))
try:
for x in range(1,30):
# Liking the picture
like_button = webdriver.find_element_by_xpath('//*[#aria-label="Like"]')
like_button.click()
likes += 1
sleep(5)
# Comments and tracker
comm_prob = randint(1,11)
print('{}_{}: {}'.format(hashtag, x,comm_prob))
if comm_prob > 7:
comments += 1
#webdriver.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]/section[1]/span[2]/button').click()
comment_button = webdriver.find_element_by_xpath('//*[#aria-label="Comment"]')
comment_button.click()
comment_box = webdriver.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/div[3]/section[3]/div/form/textarea')
if (comm_prob < 7):
comment_box.send_keys('Really cool :D!')
sleep(5)
elif (comm_prob > 6) and (comm_prob < 9):
comment_box.send_keys('Interesting work!')
sleep(5)
elif comm_prob == 9:
comment_box.send_keys('Nice gallery!')
sleep(5)
elif comm_prob == 10:
comment_box.send_keys('Cool view!')
sleep(5)
elif comm_prob == 11:
comment_box.send_keys('Wonderful view :)')
sleep(5)
# Enter to post comment
comment_box.send_keys(Keys.ENTER)
sleep(3)
followed += 1
nxt = webdriver.find_element_by_link_text('Next')
nxt.click()
sleep(2)
nxt = webdriver.find_element_by_link_text('Next')
nxt.click()
sleep(2)
nxt = webdriver.find_element_by_link_text('Next')
nxt.click()
sleep(2)
# some hashtag stops refreshing photos (it may happen sometimes), it continues to the next
except:
continue
I have managed to make it work again using the above code. Right now it is liking a picture and skipping one. I tried to remove one of the "Next" blocks but it won't go to the next picture anymore...well, better than nothing.
I guess your logical bug is here:
if webdriver.find_element_by_xpath('/html/body/div[5]/div[2]/div/article/header/div[2]/div[1]/div/span/a').text != 'x':
The /html/body/div[5]/div[2]/div/article/header/div[2]/div[1]/div/span/a locator is matching the opened thumbnail user name but you are comparing it with 'x' string.
So since the user name is not equals to 'x', you will always enter this block and will actually like and unlike in endless loop the same, the first user.
Moreover, there is else case for the above if.
It checks for clicks counter. So since you will always click on the click inside the if and just increase the clicks counter you will never click with webdriver.find_element_by_xpath('/html/body/div[5]/div[1]/div/div/a').click() but you will try to perform click with webdriver.find_element_by_xpath('/html/body/div[5]/div[1]/div/div/a[2]').click().
However I see this locator is wrong, no such element. So nothing will be clicked, you will stay inside the first opened thumbnail and click on "like" button there endlessly.
Additionally to the above I would recommend you never use the automatically generated locators like those you are using here. they are extremely unreliable. You have yo learn how to make correct locators.

how to use "if" to test the presence of an element in the webpage with python?

I created a loop (while True) to automate a task on the site with python. This code clicks on two fields until an element appears on the page
(browser.find_element_by_id ('formComp: buttonBack').
When this element appears, I want the loop to stop and go to the next block of code.
I tested it that way, but it made a mistake. Python reported that the element "formComp: buttonback" was not found. But that's just it, if not found continue the loop:
while (browser.find_element_by_id('formComp:repeatCompromissoLista:0:tableRealizacao:0:subtableVinculacoes:0:vinculacao_input')):
vinc = wait.until(EC.presence_of_element_located((By.ID, 'formComp:repeatCompromissoLista:0:tableRealizacao:0:subtableVinculacoes:0:vinculacao_input')))
vinc = browser.find_element_by_id('formComp:repeatCompromissoLista:0:tableRealizacao:0:subtableVinculacoes:0:vinculacao_input')
vinc.send_keys('400')
enterElem5 = wait.until(EC.element_to_be_clickable((By.ID, 'formComp:buttonConfirmar')))
enterElem5 = browser.find_element_by_id('formComp:buttonConfirmar')
enterElem5.send_keys(Keys.ENTER)
time.sleep(int(segundosv))
if (browser.find_element_by_id('formComp:buttonRetornar')== True):
break
else:
continue
Try like this hope this helps.Check the length count of the button more than 0.
if (len(browser.find_elements_by_id('formComp:buttonRetornar'))>0):
break
else:
continue
find_element_by_id() does not return False when an element is not found. Instead, it raises selenium.common.exceptions.NoSuchElementException. You can handle the exception to get the flow control you are looking for:
try:
browser.find_element_by_id('formComp:buttonRetornar')
break
except NoSuchElementException:
continue

Resources