0

HTTP 接続を使用してデータをダウンロードする、データ集約型のPythonスクリプトがあります。私は通常、一晩中実行します。接続に失敗したり、Web サイトが一時的に利用できなくなったりすることがあります。これらの例外をキャッチして定期的に再試行し、5 分間の再試行後に正常に終了する (そしてエラーをログに記録する) 基本的なエラー処理があります。

ただし、ジョブがフリーズする場合があることに気付きました。エラーはスローされず、ジョブはまだ実行されており、最後の印刷メッセージから数時間後になることもあります。

最善の方法は次のとおりです。

  • Python スクリプトを監視し、
  • 一定時間経過後に応答がないかどうかを検出し、
  • 応答がない場合は終了し、
  • 別のものを開始しますか?

アップデート

ご協力ありがとうございました。何人かが指摘しているように、urllibsocketモジュールにはタイムアウトが正しく設定されていません。Freebaseおよびurllib2モジュールでPython 2.5を使用し、 MetawebErrorsおよびurllib2.URLErrorsをキャッチして処理しています。最後のスクリプトが 12 時間ハングした後の err 出力のサンプルを次に示します。

  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を使用していて、3 番目のurllib2.urlopenオプションにアクセスできないため、このエラーを監視してキャッチする別の方法はありますか? たとえば、私はURLErrorsをキャッチしています - urllib2またはソケットに別のタイプのエラーがあり、それをキャッチできるのでしょうか?

4

4 に答える 4

7

スクリプトにバグがあるようです。答えは、バグを監視することではなく、バグを探して修正することです。

いくつかのコードを見ずにバグを見つけるのを手伝うことはできません。ただし、一般的な考え方として、ログを使用して問題が発生している場所を特定し、コードのどの部分にバグがないかについての信頼を構築するのに役立つ単体テストを作成することをお勧めします。

もう1つのアイデアは、Ctrl-Cを使用して「スタック」プログラムを中断し、トレースバックメッセージを調査することです。プログラムが最後に実行された行が表示されます。それはあなたにスクリプトがうまくいかないところの手がかりを与えるかもしれません。

于 2010-11-04T01:42:32.923 に答える
4

このプログラムは Web 通信を行っているので、Charles http://www.charlesproxy.com/のようなデバッグ プロキシを起動して、スクリプトとサーバーの間のやり取りで異常が発生していないかどうかを確認します。

また、ソケット モジュールにはデフォルトでタイムアウトが設定されていないため、ハングする可能性があることも考慮してください。ただし、python 2.6 以降では、3 番目の引数を urllib2.urlopen に渡すことができ (urllib2 を使用している場合)、リクエストのタイムアウト期間を秒単位で指定できます。そうすれば、スクリプトは、おそらく非協力的なサーバーからの応答を待つのではなく、エラーになります。まだ行っていない場合は、より複雑なことを試す前に、これらのことを確認します.

Python 2.5 の更新: Python < 2.6 でこれを行うには、urllib2 が使用するソケット モジュールでタイムアウト値を直接設定する必要があります。私はこれを試していませんが、おそらくうまくいきます。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)
于 2010-11-04T02:25:49.120 に答える
1

要求したことを実行する簡単な方法は、現在のプログラムから出力を監視する別のハーベスティングプログラムに送信されたUDPパケットを利用することです。一定時間内にパケットを受信しない場合、他のPythonプロセスを強制終了し、別のPythonプロセスを再起動します

于 2010-11-04T01:41:53.247 に答える
1

pdbスクリプトがフリーズしていると思われる場合は、スクリプトを実行して侵入することができます。それだけでは機能しませんが、フリーズする理由を理解するのに役立つかもしれません.

于 2010-11-04T01:45:23.140 に答える