2011-10-31 15 views
2

可用性のために一連のURLをテストしているスクリプトを実行しています。Pythonソケットエラーの復元力/回避策

これは機能の1つです。

def checkUrl(url): # Only downloads headers, returns status code. 
    p = urlparse(url) 
    conn = httplib.HTTPConnection(p.netloc) 
    conn.request('HEAD', p.path) 
    resp = conn.getresponse() 
    return resp.status 

時々、VPSの接続が失われ、そのときにスクリプト全体がクラッシュすることがあります。

File "/usr/lib/python2.6/httplib.py", line 914, in request 
    self._send_request(method, url, body, headers) 
File "/usr/lib/python2.6/httplib.py", line 951, in _send_request 
    self.endheaders() 
File "/usr/lib/python2.6/httplib.py", line 908, in endheaders 
    self._send_output() 
File "/usr/lib/python2.6/httplib.py", line 780, in _send_output 
    self.send(msg) 
File "/usr/lib/python2.6/httplib.py", line 739, in send 
    self.connect() 
File "/usr/lib/python2.6/httplib.py", line 720, in connect 
    self.timeout) 
File "/usr/lib/python2.6/socket.py", line 561, in create_connection 
    raise error, msg 
socket.error: [Errno 101] Network is unreachable 

これはPythonでこのようなエラーを処理することに全く慣れていません。

ネットワーク接続が一時的に失われたときにスクリプトがクラッシュするのを防ぐ適切な方法は何ですか?


編集:私はこれで終わった

- フィードバックを?

def checkUrl(url): # Only downloads headers, returns status code. 
    try: 
     p = urlparse(url) 
     conn = httplib.HTTPConnection(p.netloc) 
     conn.request('HEAD', p.path) 
     resp = conn.getresponse() 
     return resp.status 
    except IOError, e: 
     if e.errno == 101: 
      print "Network Error" 
      time.sleep(1) 
      checkUrl(url) 
     else: 
      raise 

私は完全にかかわらず..

+0

質問をする前にPythonのドキュメントを読んでください:http://docs.python.org/tutorial/errors.html – gecco

答えて

3

あなただけのこのネットワークを処理したい場合は101に到達不能であり、他の例外がエラーを投げる、あなたは例えば次の操作を行うことができましょう。それはスタンドとしてあなたのソリューションと

from errno import ENETUNREACH 

try: 
    # tricky code goes here 

except IOError as e: 
    # an IOError exception occurred (socket.error is a subclass) 
    if e.errno == ENETUNREACH: 
     # now we had the error code 101, network unreachable 
     do_some_recovery 
    else: 
     # other exceptions we reraise again 
     raise 
+0

ありがとう、非常に参考になりました。 do_some_recoveryが最終的に同じ関数を再び呼び出すのは理にかなっていますか? – some1

+2

明らかにそうかもしれませんが、すぐにはありません。または、エラーメッセージを表示してループを続行するだけです。もちろん、他のエラーもあります。たとえば、DNSサーバーに接続できないなどのエラーがあります。あなたは、プログラム内のすべてのIOError例外を処理し、それらを再評価しないことが望ましいです。チュートリアルを読んでから、http://docs.python.org/library/socket.html#socketを読んでください。エラー –

4

問題は、単一のURL(>デフォルトでは1000)にあまりにも多くのエラーがある場合、原因再帰にスタック領域が不足するつもりです。また、余分なスタックフレームは、トレースバックを読みにくくする可能性があります(500コールでcheckURL)。

def checkUrl(url): # Only downloads headers, returns status code. 
    while True: 
     try: 
      p = urlparse(url) 
      conn = httplib.HTTPConnection(p.netloc) 
      conn.request('HEAD', p.path) 
      resp = conn.getresponse() 
      return resp.status 
     except IOError as e: 
      if e.errno == 101: 
       print "Network Error" 
       time.sleep(1) 
     except: 
      raise 

また、あなたはあなたのtryの最後の節はelseexcept裸ないようにしたい:そうは次のように私は、反復することを書き換えると思います。 スイートの最後のステートメントがreturnであるため、制御がtryスイートを通過する場合にのみ、elseが実行されます。

これは、非常に簡単に再試行できる回数を制限することができます。 while True:行をfor _ in xrange(5)に変更するか、受け入れることを再試行してください。 5回の試行後にサイトに接続できない場合は、Noneが返されます。関数の最後にreturnまたはraise SomeExceptionを追加することで、何かを返すか例外を発生させることができます(forまたはwhile行と同じインデントされます)。

+0

偉大なフィードバックは、非常に親切に感謝します。 – some1