bob_tet
bob_tet

Reputation: 11

Explicit Wait for element present in Python3

I'm trying to use explicit wait selenium webdriver but for several days my attempts have not been successful. I read several times http://selenium-python.readthedocs.io/waits.html#explicit-waits but it did not help me.

this is the latest version of the code and I get errors:

#-----step1
change_element = driver.find_element_by_xpath("//img [@ title= 'settings']").click()  
#-----wait
try:
    change_element = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,"//input [@ id= 'NAME']"))) 
#Error: selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: //input [@ id= 'NAME']
except:
    time.sleep(3)
#-----step2
driver.find_element_by_xpath("//input [@ id= 'NAME']").clear() 
#Error: selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: //input [@ id= 'NAME']    
input_element = driver.find_element_by_xpath("//input [@ id= 'NAME']")
input_element.send_keys(v[1])

But if I use the code below then there are no errors:

change_element = driver.find_element_by_xpath("//img [@ title= 'settings']").click()
time.sleep(25)
driver.find_element_by_xpath("//input [@ id= 'NAME']").clear()
input_element_FIO = driver.find_element_by_xpath("//input [@ id= 'NAME']")
input_element_FIO.send_keys(v[1])

my mistake in structure "try except" but I do not understand how to write it using the algorithm below:

1 I want to wait for the download of the item @ id= 'NAME' each 10 sec, then execute  driver.find_element_by_xpath("//input [@ id= 'NAME']").clear()
2 if the element  @ id= 'NAME' not loaded then wait 3 sec
3 if an item is loaded @ id= 'NAME' then execute driver.find_element_by_xpath("//input [@ id= 'NAME']").clear()
4 if the element @ id= 'NAME' not loaded then wait again 10 sec , then execute  driver.find_element_by_xpath("//input [@ id= 'NAME']").clear()

Can anyone please help me?

Upvotes: 1

Views: 777

Answers (1)

anonygoose
anonygoose

Reputation: 739

So let's have a think about what all this code and retying is attempting to achieve.

1 I want to wait for the download of the item @ id= 'NAME' each 10 sec, then execute  driver.find_element_by_xpath("//input [@ id= 'NAME']").clear()
2 if the element  @ id= 'NAME' not loaded then wait 3 sec
3 if an item is loaded @ id= 'NAME' then execute driver.find_element_by_xpath("//input [@ id= 'NAME']").clear()
4 if the element @ id= 'NAME' not loaded then wait again 10 sec , then execute  driver.find_element_by_xpath("//input [@ id= 'NAME']").clear()

This can be broken down to one statement

I want to wait until the element is there before I interact with it

You can accomplish this by importing and using WebDriverWait, as you already have.

The second argument on WebDriverWait tells WebDriver how long in seconds to keep trying to locate this element for. It will try to locate the element every few hundred milliseconds during this time. If this defined time passes without WebDriver finding the element it will raise a TimeoutException and your script will exit.

I don't think you want to be catching this exception, as your test is likely in an error state if you cannot find the element you're looking for at this point.

Here's an example on a WebDriver training website that shows the usage:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

path = 'C:/Users/will/Downloads/chromedriver1/chromedriver.exe'
driver = webdriver.Chrome(path)

time.sleep(5)

driver.get("http://the-internet.herokuapp.com/dynamic_loading/1")

driver.find_element_by_xpath("//button[text()='Start']").click()

hwElem = WebDriverWait(driver, 30).until(EC.visibility_of_element_located((By.XPATH, "//h4[text()='Hello World!']")))

print(hwElem.text)

driver.quit()

If you're still getting NoSuchElementException while using a WebDriverWait in the above manner (and you're not catching the exception!) then I would say it's an error at a different part of your script, as there's no way it can throw that exception from inside a WebDriverWait.until used in this fashion.

A few additional tips:

  • Don't catch your exceptions unless you know what you're doing, especially not all of them. This can be very confusing, and lead you down the wrong path trying to figure out what's wrong
  • As this appears to be a dynamic element, it may be hidden on the page and waiting to appear, so use EC.visibility_of_element_located to avoid potentially interacting with an item that is present but not visible
  • WebDriverWait.until will handle its own retry attempts, you don't need to run it more than once, just increase the timeout duration if you know the website may not show this element for 25+ seconds. It will check every 200 milliseconds, I think it is. 500 milliseconds at most.

Upvotes: 2

Related Questions