2016-04-12 8 views
1

システムコールが中断されたために内部Webサイトに断続的な問題が発生しているところで、最近問題が発生しました。 urllib2を使用してウェブサイトにアクセスしています。私は、正確なコードを共有するが、ここでは、我々はそれを行う方法基本的にはできません。中断されたシステムコールの再試行で問題が発生しました

payload = {'userName': user_name, 
      'emailAddress': email_address, 
      'password': password} 
headers = {'Accept': 'application/json', 
      'Content-Type': 'application/json', 
      'Authorization': token} 
values = json.dumps(payload) 
req = urllib2.Request(url, values, headers) 

try: 
    response = urllib2.urlopen(req, timeout=30) 
    break 
except IOError, e: 
    if e.errno != errno.EINTR: 
     print e.errno 
    raise 

我々はerronoと発生した例外を記録します。例外は次のとおりです。

IOError: <urlopen error [Errno 4] Interrupted system call> 

そして、errnoはNoneです。私はそれが4となることを期待しました。

Python 2.7でこのエラーをキャッチする良い方法はありますか?私はPEP475を認識していますが、今はPython 3にアップグレードできません。

+0

:少なくともいくつかの例をカバーすることができるもの

?ある時点で、 'socket.error'sが' IOError'のサブクラスに変更され、引数の引き渡しやその結果の属性値の大量の原因となりました。 –

+0

私たちはPython 2.7を使用しています –

+0

これはhttps://bugs.python.org/issue6471、または少なくとも関連するかもしれません。 –

答えて

3

<urlopen error [Errno 4] Interrupted system call>は、それがIOErrorをサブクラスurllib2、から実際にURLErrorであることを示しているが、完全に異なった引数を処理します。そのため属性errnostrerrorは初期化されません。この両方が理由のように文字列を渡します

 raise URLError("qop '%s' is not supported." % qop) 

をし、他のソースからの例外をラップ:あなたはいつもの場所でerrnoにを見つけることができません理由です

try: 
     h.request(req.get_method(), req.get_selector(), req.data, headers) 
    except socket.error, err: # XXX what error? 
     h.close() 
     raise URLError(err) 

>>> try:      
    urlopen('http://asdf') 
except URLError, e: 
    pass 
... 
>>> e 
URLError(gaierror(-2, 'Name or service not known'),) 
>>> e.errno 
>>> e.reason 
gaierror(-2, 'Name or service not known') 
>>> e.reason.errno 
-2 

これはこの場合に機能しましたが、の理由属性は文字列またはsocket.errorです。 has (had) its own problems with errno

URLErrorでurllib2.pyの定義:

class URLError(IOError): 
    # URLError is a sub-type of IOError, but it doesn't share any of 
    # the implementation. need to override __init__ and __str__. 
    # It sets self.args for compatibility with other EnvironmentError 
    # subclasses, but args doesn't have the typical format with errno in 
    # slot 0 and strerror in slot 1. This may be better than nothing. 
    def __init__(self, reason): 
     self.args = reason, 
     self.reason = reason 

    def __str__(self): 
     return '<urlopen error %s>' % self.reason 

だから、長い話短い、それは恐ろしい混乱です。

e.reasonを確認する必要があります
  1. それは単なる文字列ですか?もしそうなら、どこにもエラー番号はありません。
  2. socket.errorですか?それを扱う再びのerrno属性は、で発生させることができるため、設定を解除するか、Noneにすることができます。
  3. サブクラスIOErrorまたはOSError(サブクラスEnvironmentError)ですか? errnoの属性を読んでください。

これはあなたのケースでは過度に慎重である可能性がありますが、エッジを理解することは良いことです。 Tornado had similar issuesで、utility function to get errno from exceptionを使用していますが、残念ながらその機能はURLエラーでは機能しません。正確に2をPYTHON

while True: # or some amount of retries 
    try: 
     response = urllib2.urlopen(req, timeout=30) 
     break 
    except URLError, e: 
     if getattr(e.reason, 'errno', None) == errno.EINTR: 
      # Retry 
      continue 
+0

私は 'URLError'のソースを見ましたが、最初にそのエラーをチェックする必要があることを認識していませんでした。私はそれを試してみましょう。実際にエラーが発生するウェブサイトであるかどうかはまだ分かりませんので、確認に時間がかかることがあります。 –

+0

あなたのコードは私たちよりはるかに簡潔ですが、ほとんど同じです。私たちはたくさんのログを追加するだけです。このアプローチが有効な場合は、少しリファクタリングして少しはっきりします –

関連する問題