krwlr
Апрель 11, 2010 13:51:50
Всем доброго дня! Прошу помощи так как возникла маленькая проблема, а как решить пока не знаю.
Начну с кода:
import socket
impor urllib2
socket.setdefaulttimeout(0) # Провоцируем вызов ошибки
for line in array:
try:
connect_to_host = lambda get_request : urllib2.urlopen(get_request).read()
content = connect_to_host(line)
...
except urllib2.URLError, errmsg:
print(line, errmsg)
connect_to_host(line)
Но обрабатывается ошибка только один раз, потом при вызове connect_to_host(line.strip()) - выбивает исключение.
Нужен совет, как это побороть!? То есть чтоб повторно обрабатывалось исключение.. :)
Zubchick
Апрель 11, 2010 14:49:33
вы объявили функцию connect_to_host в теле try, а вызываете и в except
krwlr
Апрель 11, 2010 15:18:37
Эммм… не совсем вас поняла. Из except'a нельзя вызвать функцию объявленную в блоке try? Может я неправильно вас поняла.
Просто нужно чтоб при возникновении ошибки, функция вызвалась с тем же параметром. Т.е. передаётся запрос на сервер, если истекает тайм-аут, вызывается исключение и вновь создаем соединение с хостом, но с той же строкой, что не удалась. Не хочется выносить подключение в отдельную функцию, важна скорость.. даже полторы минуты разницы :)
P.S. пробовала переписать код на ruby - работает, но функция не видна вне блока {}, кошерно вызывается redo.
Вроде на руби и проще, и скорость программы выше (за счет регулярных выражений), но … нужно решить на питоне.
Ed
Апрель 11, 2010 15:49:21
Непонятно зачем вообще вам эта лямбда, честно говоря.
Я может не понял идею, но вот так исключение будет перехвачено в каждый раз:
import socket
import urllib2
socket.setdefaulttimeout(0)
for line in ("http://google.com", "http://ya.ru"):
for i in (1,2):
try:
content = urllib2.urlopen(line).read()
break
except urllib2.URLError, errmsg:
print(">>>", line, errmsg)
krwlr
Апрель 11, 2010 16:20:48
Потому что по истечению тайм-аута, мне нужно повторить запрос пока он не будет положительным.
Суть в том, чтоб не ждать долгого ответа от сервера, подключились, создали запрос, таймаут? - повторили этот же запрос, обработали его и дальше по списку..
Ed
Апрель 11, 2010 17:10:33
Ну и причем здесь лямбда? Если хотите повторять запрос бесконечно, пока он не выполнится, то вместо for i in (1,2) используйте бесконечный цикл.
krwlr
Апрель 11, 2010 17:34:44
Я удивляюсь и вами и собой)) Особенно, собой.. неужели я так плохо объясняю!? :)
Вы меня не поняли, for i in (1,2) - это перебор элемента из массива и с последующей отправкой его (элемента серверу). Так вот, если возникло исключение, то нужно повторно отправить на сервер ЭТОТ элемент массива. Не просто перехватить ошибку, сообщить и пойти дальше, оставив этот элемент просто так..
Фуф, выдохнула..)
Ed
Апрель 11, 2010 17:46:02
Вы объясняете действительно не очень. Давайте по порядку разбираться. В вашем изначальном коде было 2 вызова вашей лямбды. Поэтому я сделал вам пример с двумя повторениями запроса и усомнился попутно в нужности лямбды. Потом вы написали, что хотите бесконечно повторять запросы, пока они не будут положительными. Я посоветовал изменить цикл на бесконечный. Вы мой код пробовали?
for i in (1,2) - это не то, что вы думаете, а просто повторение одного и того же запроса 2 раза. Если посмотреть внимательно, то будет видно, что i внутри цикла не используется.
krwlr
Апрель 11, 2010 18:09:41
Ed, спасибо вам за терпение :)
Итак, насчет: for i in (1,2) - Да, заговорилась, имела в виду свой цикл for line in array.
Насчет for i in (1,2) - запрос постоянно два раза повторять не нужно. Его повторить нужно лишь в случае, если возникла ошибка URLError.
Ed
Потом вы написали, что хотите бесконечно повторять запросы, пока они не будут положительными.
Если возникла ошибка - обрабатываем и вызываем снова функцию соединения с хостом с повторной отправкой неудавшегося сообщения. Если вновь ошибка возникла - опять обрабатываем, опять передаём, и так по кругу.. Но, очень важно: тот элемент который не удалось отправить. Не следующий. Для этих целей я использовала повторный вызов lambda-функции из except'a. Но он обрабатывается раз. И всё.(((
Ed
Апрель 11, 2010 18:15:24
krwlr
Его повторить нужно лишь в случае, если возникла ошибка URLError.
Он и не повторяется. Обратите внимание на break. Он обеспечивает выход из цикла повторения, если исключения не произошло.
Кстати, если запросы у вас идут к разным сайтам я бы посоветовал слегка изменить алгоритм. Не долбить один сайт, а переходить сразу к другому и только когда весь список перебрали опять пытаться послать запрос этому сайту. И бесконечное количество попыток - это тоже не очень хорошо. Я бы все таки ограничился каким-то конечным количеством.