-1

I am trying to use the selenium webdriver to click the go back button on the page. Sometimes, it might fail on the first time due to loading, so I put the code in a while try except block to make it retry after failing:

while True:
    try:
        driver.find_element_by_class_name("back_button")
        driver.click()
    except:
        time.sleep(1)
        print("Unable to go back")
        continue
    break

Ideally, the code is supposed to move on when the piece in the try block gets successfully executed, but I found sometimes it still attempts to click the go back button when it has already been on the previous page. It then gets stuck in the while loop forever because there is no go back button on that page. What could be the potential reason for that?

Chiliboo
  • 57
  • 1
  • 4
  • `except:` with no exception (such as `except TimeoutException:`) is very dangerous practice in Selenium, and programming in general. What exception are you trying to catch here? If you specify the exception in your `except` block, it may become more clear what is going wrong in your code. It is also difficult to troubleshoot your issue without knowing the exception, and without knowing the context of the page you are automating. – CEH Dec 02 '19 at 16:01
  • I am trying to catch the `ElementNotInteractableException` here. – Chiliboo Dec 02 '19 at 16:15
  • That makes sense, that error tends to get thrown if a page is not fully finished loading. I will add an additional workaround for this issue if the error gets thrown. – CEH Dec 02 '19 at 16:16

1 Answers1

2

If your code is failing on the first time due to loading, like you said in your problem description, wrapping this in try / except surrounded by a while(true) loop is not a good way to handle this, because you may end up with certain conditions that get you stuck in the while(true) loop.

It's better to just invoke WebDriverWait on the element you wish to load before clicking. Wrapping things in try / except should really be the last resort.

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# need the above import statements

back_button = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.CLASS_NAME, "back_button")))

back_button.click()

# alternative -- if this code STILL throws ElementNotInteractable, try the below:
# driver.execute_script("arguments[0].click();", back_button)
# ^ this clicks with Javascript, which can work around ElementNotInteractable.

If you really want to wrap this in a try / except block to check for cases where back_button has not loaded in 10 seconds, you can use this:

from selenium.common.exceptions import TimeoutException
# import the exception you need to catch

try:
    back_button = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.CLASS_NAME, "back_button")))

    back_button.click()
except TimeoutException: # WebDriverWait throws TimeoutException if it fails
    print("back_button did not appear on page within 10 seconds.")

If your click() really only fails due to loading issue, the above code should eliminate your need for try / except completely.

Also worth mentioning this, in addition to comment I left on your question -- using except: without any exception to catch is very dangerous practice, because you really have no idea why your code is failing. In the future when using except:, you should really look for a specific exception such as except TimeoutException: or except NoSuchElementException:. This will save you from a debugging nightmare in the future.

CEH
  • 5,701
  • 2
  • 16
  • 40