Как я могу контролировать «застрявший» скрипт Python? - PullRequest
0 голосов
/ 04 ноября 2010

У меня есть интенсивный для данных Python скрипт, который использует HTTP-соединения для загрузки данных.Я обычно запускаю его на ночь.Иногда соединение не будет установлено, или веб-сайт будет на мгновение недоступен.У меня есть базовая обработка ошибок, которая перехватывает эти исключения и периодически повторяет попытки, корректно завершая работу (и регистрируя ошибки) после 5 минут повторных попыток.

Однако я заметил, что иногда работа просто зависает.Ошибка не выдается, и задание все еще выполняется, иногда через несколько часов после последнего сообщения печати.

Как лучше всего:

  • монитор скрипт Python,
  • обнаружение , если он не отвечаетчерез заданный интервал
  • выход это, если он не отвечает,
  • и запуск еще один?

ОБНОВЛЕНИЕ

Спасибо всем за помощь.Как отмечали некоторые из вас, для модулей urllib и socket тайм-ауты не установлены правильно.Я использую Python 2.5 с модулями Freebase и urllib2 , а также ловлю и обрабатываю MetawebErrors и urllib2.URLErrors .Вот пример вывода ошибок после того, как последний скрипт завис на 12 часов:

  File "/home/matthew/dev/projects/myapp_module/project/app/myapp/contrib/freebase/api/session.py", line 369, in _httpreq_json
    resp, body = self._httpreq(*args, **kws)
  File "/home/matthew/dev/projects/myapp_module/project/app/myapp/contrib/freebase/api/session.py", line 355, in _httpreq
    return self._http_request(url, method, body, headers)
  File "/home/matthew/dev/projects/myapp_module/project/app/myapp/contrib/freebase/api/httpclients.py", line 33, in __call__
    resp = self.opener.open(req)
  File "/usr/lib/python2.5/urllib2.py", line 381, in open
    response = self._open(req, data)
  File "/usr/lib/python2.5/urllib2.py", line 399, in _open
    '_open', req)
  File "/usr/lib/python2.5/urllib2.py", line 360, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.5/urllib2.py", line 1107, in http_open
    return self.do_open(httplib.HTTPConnection, req)
  File "/usr/lib/python2.5/urllib2.py", line 1080, in do_open
    r = h.getresponse()
  File "/usr/lib/python2.5/httplib.py", line 928, in getresponse
    response.begin()
  File "/usr/lib/python2.5/httplib.py", line 385, in begin
    version, status, reason = self._read_status()
  File "/usr/lib/python2.5/httplib.py", line 343, in _read_status
    line = self.fp.readline()
  File "/usr/lib/python2.5/socket.py", line 372, in readline
    data = recv(1)
KeyboardInterrupt

Вы увидите ошибку сокета внизу.Поскольку я использую Python 2.5 и не имею доступа к третьему параметру urllib2.urlopen , есть ли другой способ отслеживать и отлавливать эту ошибку?Например, я ловлю URLErrrors - есть ли другой тип ошибки в urllib2 или сокете , который я могу поймать, который поможет мне?

Ответы [ 4 ]

6 голосов
/ 04 ноября 2010

Похоже, в вашем скрипте есть ошибка. Ответ не в том, чтобы отслеживать ошибку, а в том, чтобы выследить ошибку и исправить ее.

Мы не можем помочь вам найти ошибку, не увидев некоторый код. Но в качестве общей идеи вы можете использовать ведение журнала, чтобы точно определить, где возникает проблема, и написать модульных тестов , чтобы помочь вам обрести уверенность в том, какие части вашего кода не содержат ошибку.

Другая идея состоит в том, чтобы разбить вашу «застрявшую» программу с помощью Ctrl-C и изучить сообщение трассировки. Он покажет вам, какую строку ваша программа выполняла в последний раз. Это может дать вам подсказку, где сценарий работает неправильно.

4 голосов
/ 04 ноября 2010

Поскольку программа осуществляет веб-общение, я бы запустил прокси-сервер отладки, такой как Charles http://www.charlesproxy.com/, и посмотрел, не происходит ли что-нибудь странное между вашим скриптом и сервером.

Также учтите, что модуль сокета не имеет времени ожидания, установленного по умолчанию, и поэтому может зависать. Начиная с python 2.6, однако, вы можете передать третий аргумент urllib2.urlopen (если вы используете urllib2, то есть), указав период ожидания запроса в секундах. Таким образом, скрипт будет выдавать ошибку, а не впадать в кататоническое ожидание ответа от, возможно, неработающего сервера. Если вы еще этого не сделали, я бы проверил эти вещи, прежде чем пытаться что-то более сложное.

Обновление для python 2.5: Чтобы сделать это в python <2.6, вы должны установить значение тайм-аута непосредственно в модуле сокета, который использует urllib2. Я не пробовал это, но, вероятно, работает. Нашел эту информацию на <a href="http://www.voidspace.org.uk/python/articles/urllib2.shtml" rel="nofollow">http://www.voidspace.org.uk/python/articles/urllib2.shtml:

import socket
import urllib2

# timeout in seconds
timeout = 10
socket.setdefaulttimeout(timeout)

# this call to urllib2.urlopen now uses the default timeout
# we have set in the socket module
req = urllib2.Request('http://www.voidspace.org.uk')
response = urllib2.urlopen(req)
1 голос
/ 04 ноября 2010

Вы можете запустить свой скрипт в pdb и взломать его, если вы подозреваете, что он заморожен. Он не будет работать сам по себе, но может помочь вам понять, почему он замерзает.

1 голос
/ 04 ноября 2010

простой способ сделать то, что вы просите, - это использовать пакеты UDP, отправленные вашей текущей программой другой программе сбора данных, которая контролирует вывод.Если он не получает пакет в течение определенного времени, он убивает другой процесс Python, а затем перезапускает другой

...