Я использую 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