Моя программа на Python всегда прерывает мое интернет-соединение после нескольких часов работы, как мне отладить и исправить эту проблему?

Я пишу скрипт python, проверяющий/отслеживающий состояние нескольких серверов/веб-сайтов (время отклика и тому подобное), это программа с графическим интерфейсом, и я использую отдельный поток для проверки разных серверов/веб-сайтов, а базовая структура каждого потока использует бесконечный цикл while для запроса этого сайта каждый случайный период времени (от 15 до 30 секунд), после внесения изменений на веб-сайте/сервере каждый поток запускает новый поток для тщательной проверки (запрос дополнительных страниц и тому подобного).

Проблема в том, что мое интернет-соединение всегда блокировалось/забивалось/искажалось после нескольких часов работы этого скрипта, ситуация такова, что со стороны моего скрипта у меня истекало время ожидания ошибки urlopen каждый раз, когда он запрашивает страницу, а со стороны моего браузера FireFox Я не могу открыть ни один сайт. Но странно то, что в тот момент, когда я закрываю свой скрипт, мое интернет-соединение немедленно возобновляется, что означает, что теперь я могу просматривать любой сайт через свой браузер, так что это должен быть скрипт, вызывающий все проблемы.

Я тщательно проверил программу и даже использую del для удаления любого соединения после его использования, но все равно получаю ту же проблему. Я использую только urllib2, urllib, mechanize для выполнения сетевых запросов.

Кто-нибудь знает, почему такое происходит? Как отладить эту проблему? Есть ли инструмент или что-то для проверки состояния моей сети в случае возникновения такой ситуации? Это действительно беспокоит меня какое-то время...

Кстати я за VPN, это как-то связано с этой проблемой? Хотя я так не думаю, потому что моя сеть всегда включается после закрытия скрипта, а VPN-соединение никогда не прерывается (как кажется) в течение всего процесса.

[Обновления:]

Только что нашел больше информации об этой проблеме, когда моя программа прерывает подключение к Интернету, ну, это не совсем «отключено», я имею в виду, что я не могу открыть какой-либо сайт в своем браузере или всегда получаю сообщение об ошибке urlopen, но я все еще могу получить ответьте, используя «ping google.com» в строке cmd. И когда я вручную разорвал VPN-соединение, а затем повторно набрал, не закрывая мою программу, она снова начинает работать, и я также могу выходить в сеть через свой браузер. Почему это происходит?


person Shane    schedule 14.01.2011    source источник
comment
del редко бывает полезен. Я предполагаю, что вы закрываете ()? Этого должно быть достаточно. Не знаю, как помочь вам отладить его.   -  person Lennart Regebro    schedule 14.01.2011
comment
@Lennart: Итак: response = urllib2.urlopen("http://google.com"), del response закроет это соединение?   -  person Shane    schedule 14.01.2011
comment
Нет, del response просто удаляет локальную переменную response, тем самым удаляя одну ссылку на объект urllib. Если это единственная ссылка на объект ответа, она будет удалена и, да, закрыта. Но это не следует делать вручную с помощью del, вместо этого вы должны позволить ему выйти за рамки. Если вы не уверены, вы можете вручную вызывать close() для объектов, но в этом нет необходимости. Но это не похоже на проблему с вашим приложением.   -  person Rosh Oxymoron    schedule 14.01.2011
comment
@Shane: Нет, del пометит его как сборщик мусора. Он будет закрыт при сборе, что может быть совершенно в другой раз. Вы должны вызвать response.close().   -  person Lennart Regebro    schedule 14.01.2011
comment
@Rosh: я просто не знаю, почему мой скрипт отключает мою сеть, и как только скрипт закрывается, моя сеть немедленно включается. И каждый раз это вызвано urlopen error timed out. Это действительно разозлило меня   -  person Shane    schedule 14.01.2011
comment
@Shane: Вы звоните .close () или нет?   -  person Lennart Regebro    schedule 14.01.2011
comment
@Lennart: Еще нет, я попробую, хотя я не думаю, что это проблема ... Я просто не знаю, где искать и как найти проблему.   -  person Shane    schedule 14.01.2011
comment
@Shane: я думаю, это проблема. В конечном итоге вы получите множество открытых соединений, пока на вашем компьютере не закончатся дескрипторы. Убедитесь, что вы close() соединения, и жизнь будет прекрасна. del в значительной степени бесполезен, так как вы не можете контролировать, когда или даже если соединение будет закрыто.   -  person Lennart Regebro    schedule 14.01.2011
comment
@Lennart: я только что узнал, что все еще могу получить ответ от ping google.com, когда моя сеть не работает, хотя я не могу просматривать сайты в своем браузере, что это за проблема с сетью?   -  person Shane    schedule 15.01.2011
comment
@Shane: Похоже, у тебя слишком много открытых подключений. Открытие веб-страницы создает TCP-соединение, ping отправляет пакет ICMP, у вас заканчиваются TCP-соединения, потому что вы не используете close().   -  person Lennart Regebro    schedule 15.01.2011


Ответы (2)


Это может быть проблемой, а может и не быть, но рекомендуется всегда использовать диспетчеры контекста при работе с вещами, которые открывают ресурсы, такие как файлы или URL-адреса.

Начиная с Python 2.5 вы можете делать это с файлами:

with open('/tmp/filename', 'rt') as infile:
    data = infile.read()
    whatever(data)

И файл будет автоматически закрыт в конце блока.

urllib2 не поддерживает это автоматически, но вы можете использовать contextlib, чтобы помочь вам:

>>> import contextlib
>>> with contextlib.closing(urllib2.urlopen('http://www.python.org')) as page:
...   for line in page:
...     print(line)
<html> blablablabla</html>

Таким образом, соединение будет закрыто и удалено в конце блока with, поэтому вам не нужно об этом думать. :-)

person Lennart Regebro    schedule 14.01.2011
comment
Есть ли способ/инструмент для проверки того, что происходит в моей сети и что python делает с моей сетью, пока возникает моя проблема? - person Shane; 14.01.2011
comment
Спасибо большое. Это действительно del вызывает все проблемы, я нашел множество соединений Close_Wait с использованием netstat, и эти соединения израсходовали все ресурсы, поэтому с тех пор я получил тайм-аут urlerror. После замены всех del на .close() теперь все работает нормально. ^_^ - person Shane; 17.01.2011

  • Возможно, вы создаете больше потоков, чем ожидаете, — отслеживайте результат threading.active_count(), чтобы проверить это.

  • Если возможно, попробуйте исключить VPN на вашем конце (или опубликуйте соответствующие части кода, чтобы мы могли его протестировать).

  • (Nettiquete) Если вы еще этого не сделали, используйте только потоки network.http.max-connections-per-server для каждого отслеживаемого сайта/узла.

  • (Для справки) urlopen возвращает подобный файлу объект — используйте .close() или del для этого объекта, иначе сокет будет находиться в состоянии CLOSE_WAIT до истечения времени ожидания.

Надеюсь, эти точки являются указателями.

person Dale Reidy    schedule 14.01.2011