У меня есть программа, которая использует urllib для периодической выборки URL, и я вижу случайные ошибки как:
Ошибка ввода-вывода (снабжают ошибку сокетом): [Errno 111] Соединение, которому отказывают.
Это работает 90% времени, но % othe r10 это перестало работать. Если повторяют выборка сразу после того, как она перестала работать, она успешно выполняется. Я не могу выяснить, почему это так. Я пытался видеть, доступны ли какие-либо порты, и они. Какие-либо идеи отладки?
Для получения дополнительной информации отслеживание стека:
File "/usr/lib/python2.6/urllib.py", line 203, in open
return getattr(self, name)(url)
File "/usr/lib/python2.6/urllib.py", line 342, in open_http
h.endheaders()
File "/usr/lib/python2.6/httplib.py", line 868, in endheaders
self._send_output()
File "/usr/lib/python2.6/httplib.py", line 740, in _send_output
self.send(msg)
File "/usr/lib/python2.6/httplib.py", line 699, in send
self.connect()
File "/usr/lib/python2.6/httplib.py", line 683, in connect
self.timeout)
File "/usr/lib/python2.6/socket.py", line 512, in create_connection
raise error, msg
Редактирование - поиск Google не очень полезен, что я вышел из него, то, что сервер, от которого я являюсь выбирающим иногда, отказывается от соединений, как я могу проверить не ошибка в моем коде, и это действительно имеет место?
Используйте сниффер пакетов, например Wireshark , чтобы посмотреть, что происходит. Вам нужно увидеть исходящий пакет с флагом SYN, входящий с флагом SYN + ACK и затем исходящий с флагом ACK. После этого порт считается открытым с локальной стороны.
Если вы видите только первый пакет, а сообщение об ошибке появляется после нескольких секунд ожидания, другая сторона вообще не отвечает (например, в случае: отключенный кабель, перегруженный сервер, ошибочно направленный пакет был отброшен) и ваш локальный сетевой стек прерывается. попытка подключения. Если вы видите пакеты RST, хост фактически отклоняет соединение. Если вы видите «Порт ICMP недоступен» или пакеты о недоступности хоста, брандмауэр или целевой хост сообщают вам о фактическом закрытии порта.
Конечно, нельзя ожидать, что служба будет доступна все время (учтите все точки отказа между вами и данными), поэтому вам следует повторить попытку позже.
Я не совсем уверен, что это вызывает. Вы можете попробовать заглянуть в свой socket.py (у меня другая версия, поэтому номера строк из трассировки не совпадают, и я боюсь, что некоторые другие детали также могут не совпадать).
В любом случае, неплохо было бы поместить код получения URL в блок try: ... except: ...
и обработать это с помощью короткой паузы и повторной попытки. URL-адрес, который вы пытаетесь получить, может быть неработающим или слишком загруженным, и это все, что вы в любом случае сможете обработать, только повторив попытку.
Получение ошибки ECONNREFUSED означает, что вашему ядру было отказано в соединении на другом конце, так что если это ошибка, то она либо в вашем ядре, либо на другом конце. Что вы можете сделать, так это отловить ошибку очень специфическим способом и повторить попытку через некоторое время, так как это, кажется, работает:
# This is Python > 2.5 code
import errno, time
for attempt in range(MAXIMUM_NUMBER_OF_ATTEMPTS):
try:
# your urllib call here
except EnvironmentError as exc: # replace " as " with ", " for Python<2.6
if exc.errno == errno.ECONNREFUSED:
time.sleep(A_COUPLE_OF_SECONDS)
else:
raise # re-raise otherwise
else: # we tried, and we had no failure, so
break
else: # we never broke out of the for loop
raise RuntimeError("maximum number of unsuccessful attempts reached")
Замените две константы, написанные прописными буквами, на ваши любимые числа.