Подтвердить что ты не робот

Помогите Firefox не реагировать при использовании Selenium WebDriver с Python?

Я использую Selenium с Python для тестирования веб-приложения; однако Firefox будет периодически переходить в состояние "Не реагировать". Пока Firefox находится в этом состоянии, script будет зависать, пока я его не закрою.

Я пробовал:

br = webdriver.Firefox()
br.set_page_load_timeout(10)

и

br = webdriver.Firefox()
br.implicitly_wait(10)

Я боюсь, что моя проблема не будет решена с помощью метода wait или timeout, так как страница Ajax. Метод .click() или .submit() отправляет POST для ответа на вопрос, а ответ - это словарь, который через JavaScript обновляет страницу с новым вопросом. (Это я понимаю из-за использования вкладки "Сеть" в инструментах разработчика Google Chrome Ctrl + Shift + I)

Возникает вопрос:

Как я могу уловить Firefox, не отвечающий в Selenium?

Я хочу поймать эту ситуацию, чтобы закрыть браузер и запустить новый.


Отредактировано после ответа ExperimentsWithCode:
Вот фрагмент моего кода, чтобы проиллюстрировать мою проблему.

def answer_questions(self):
    q = QuestionParser(self.br.page_source)
    q.add_to_db()
    qid = q.get_qid()
    # My answer
    my_answer_id = q.get_my_answer()
    self.br.find_element_by_id(my_answer_id).click()
    # Submit answer
    self.br.find_element_by_xpath('//*[contains(@id, "submit_btn_")]').click()
    try:
        find_id = "submit_btn_" + str(qid)
        element = WebDriverWait(self.br,10).until(EC.presence_of_element_located((By.ID, find_id)))
    except:
        print 'I caught you'
    self.rnd(mu=7, s=2) # a method to sleep for a random time

Я вызываю метод answer_questions() в цикле. Этот код работает нормально до тех пор, пока Firefox не сработает, и он будет висеть, пока я его не закрою. Я читал документы и боялся, что исчерпал все. Проблема не в загрузке страницы или элемента. Проблема заключается в том, что я не знаю, как обнаружить, когда Firefox сбой. WebDriverWait кажется многообещающим, но он не бросал TimeoutException, когда Firefox разбился.

Спасибо за ваше время.


Я разработал средство для своей проблемы. Вот фрагмент, который я сделал:

import os, socket
from threading import Timer
def force_timeout(self):
    os.system('taskkill /im firefox.exe /f /t')
    # for Windows
    # /im firefox.exe is to select firefox
    # /f is to forcefully kill
    # /t is to kill all child processes

for i in range(0, 1000):
    try:
        t = Timer(60, self.force_timeout)
        # run force_timeout from new thread after 60 seconds
        t.start() # start timer
        self.answer_questions()
        # if self.answer_questions() finishes before 60s, cancel timer
        t.cancel() # cancel timer
    except socket.error:
        self.new_browser() # create a new browser
        self.login()       # login
        self.go_to_questions() # Go to questions page so the loop can continue
        # Code to recover from crash here

Если метод answer_questions() не завершится через 60 секунд, force_timeout() будет запускаться из нового потока и принудительно убить firefox.exe. После прекращения работы Firefox код будет вызывать ошибку socket.error. Поймайте эту ошибку, затем выполните то, что вам нужно сделать, чтобы восстановить из-за сбоя браузера. Я считаю, что код немного грязный, но он работает именно так, как мне нужно.
Для справок: OS - Win8, Selenium Version - 2.40.0, версия для Firefox - 27.0.1

Windows Taskkill
Python threading.Timer

4b9b3361

Ответ 1

В документах Webdriver есть раздел о таких вещах, как здесь.

В документах вы можете попробовать Explicit Wait:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0

br = webdriver.Firefox()
br.get("http://somedomain/url_that_delays_loading")
try:
    element = WebDriverWait(br, 10).until(EC.presence_of_element_located((By.ID, "_element_You_Are_Need_To_Load")))
finally:
    br.quit()

Это приведет к тайм-ауту, если элемент не может быть найден за 10 секунд или вернуть элемент в этом окне.

Ответ 2

Для тех из вас, кто находится на * nix,

os.system("pkill -P %d firefox" % os.getpid())

работает красиво, чтобы убить детей Firefox вашего текущего процесса.

страница руководства pkill