It depends on the Website you are working with.
If you have a Website, that doesn't change itself, use Emilio's answer. WebDriverWait(...).until(...) is the correct / best solution for Websites, that don't change by themselves (and only by user interactions):
WebDriverWait(driver, delay, ignored_exceptions=(NoSuchElementException,StaleElementReferenceException)).until(expected_conditions.presence_of_element_located((By.ID, "my_id"))).click()
(For explanation see Emilio's answer)
If you work with a site, that changes by pushs from server or time based or something similar, the only working solution is retrying like in Rashids answer.
def retry_func(func, max_tries=MAX_TRIES):
for i in range(max_tries):
try:
return func()
except Exception as e:
if i >= max_tries - 1:
raise e
def click_button_helper(driver, selector, selector_type=By.XPATH, delay=DELAY, ignored_exceptions=IGNORED_EXCEPTIONS):
WebDriverWait(driver, delay, ignored_exceptions=ignored_exceptions).until(
EC.presence_of_element_located((selector_type, selector))).click()
def click_button(driver, selector, selector_type=By.XPATH, delay=DELAY, ignored_exceptions=IGNORED_EXCEPTIONS,
max_tries=MAX_TRIES):
retry_func(lambda: click_button_helper(driver, selector, selector_type, delay, ignored_exceptions), max_tries)
Because, sorry @Emilio, your answer doesn't address specific cases like the one Sylvan LE DEUNFF mentioned.
The following race condition is still possible (and not solved by WebDriverWait(...).until(...), but usually by retrying):
- The page is changing (e.g. after a click like in the question)
- We are trying to find the element.
- WebDriverWait(...).until(...) waits for us till our expected_conditions are fullfilled (so basically till it finishes changing)
- We found the element
- It starts changing again (by push, by reaching timestep, ...)
- We try to use it
- Bam! The element is old again.
aclassname
element is loaded? – Artemisia