Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
459 views
in Technique[技术] by (71.8m points)

How to address "WebDriverException: Message: TypeError: can't access dead object" and wait for a frame to be available using Selenium and Python

I have a rather complex webpage setup I need to test, containing nested frames.

In the actual problem the selenium code is loading new webpage contents containing a frame, which I want to switch to. In order to avoid any explicit waits, I tried the following code snippet:

self.driver.switch_to_default_content()
WebDriverWait(self.driver, 300).
        until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'frame1')))
WebDriverWait(self.driver, 300).
        until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'frame2')))

However, this snippet always fails and results in the following error:

  ...
  File "/home/adietz/Projects/Venv/nosetests/local/lib/python2.7/site-packages/selenium/webdriver/support/wait.py", line 71, in until
    value = method(self._driver)
  File "/home/adietz/Projects/Venv/nosetests/local/lib/python2.7/site-packages/selenium/webdriver/support/expected_conditions.py", line 247, in __call__
    self.frame_locator))
  File "/home/adietz/Projects/Venv/nosetests/local/lib/python2.7/site-packages/selenium/webdriver/support/expected_conditions.py", line 402, in _find_element
    raise e
WebDriverException: Message: TypeError: can't access dead object

However, if I use a sleep in addition:

time.sleep(30)
self.driver.switch_to_default_content()
WebDriverWait(self.driver, 300).
        until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'frame1')))
WebDriverWait(self.driver, 300).
        until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'frame2')))

selenium is able to find the frame inside the frame and switch to it. It looks like in the error case selenium switches to 'frame1' while 'frame2' is not yet loaded, but 'frame2' gets loaded in some other instance of 'frame1', or not recognized by selenium (maybe a bug?). So now selenium is inside some 'frame1' and for some reasons does not realize that the 'frame2' has been loaded.

The only way I can fix this (without using a long sleep) is by using this ugly piece of code:

    mustend = time.time() + 300
    while time.time() < mustend:
        try:
            self.driver.switch_to_default_content()
            self.driver.switch_to.frame(self.driver.find_element_by_id("frame1"))
            self.driver.switch_to.frame(self.driver.find_element_by_id("frame2"))               
            break
        except WebDriverException as e:
            self.log("Sleeping 1 sec")
            time.sleep(1)
    if time.time() > mustend:
        raise TimeoutException

So whenever I get a WebDriverException (dead object), I go to the top-level frame and try to switch to the inner frame - frame by frame.

Is there any other approach I can try?

Additional information

  • The iframes are nested, i.e. 'frame2' is inside 'frame1'.
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Better approach is to make your own expected_condition. For example:

class nested_frames_to_be_available_and_switch:
    def __init__(self, *args):
        """
        :param args: locators tuple of nested frames (BY.ID, "ID1"), (BY.ID, "ID2"), ...
        """
        self.locators = args

    def __call__(self, driver):
        try:
            for locator in self.locators:
                driver.switch_to.frame(driver.find_element(*locator))
        except WebDriverException:
            driver.switch_to_default_content()
            return False
        return True

WebDriverWait(driver, 300).until(nested_frames_to_be_available_and_switch((By.ID, 'frame1'), (By.ID, 'frame1')))

But maybe there is no need for that.. To tell so I need to see your html DOM.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...