2016-04-12 19 views
1

Son zamanlarda, kesintili bir sistem çağrısı nedeniyle yüklenmeyen dahili bir web sitesiyle aralıklı olarak sorun yaşadığımız bir işte karşılaştım. Web sitesine erişmek için urllib2 kullanıyoruz. Ben tam kodunu paylaşabilir, ama burada biz bunu nasıl temelde olamaz:Kesintisiz sistem çağrısı sırasında sorun giderilirken sorun oluştu

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 

Biz errono ve yükseltilmiş durum oturum. İstisna: Ve errno None'dur. Bunun olmasını bekledim 4.

Bu hatayı Python 2.7'de yakalamanın daha iyi bir yolu var mı? PEP475'in farkındayım, ancak şu anda Python 3'e geçemeyiz.

+0

Hangi piton 2 tam olarak? 'socket.error', bir noktada hataların sonuç değerlerini ve sonuçta oluşan argümanları bozmaya neden olan 'IOError' alt sınıfına değiştirildi. –

+0

Python 2.7 –

+0

kullanıyoruz Bu, https://bugs.python.org/issue6471 veya en azından ilgili olabilir. –

cevap

3

<urlopen error [Errno 4] Interrupted system call> bu IOError alt sınıfların urllib2, aslında bir URLError olduğunu gösterir, ama tamamen farklı bir bağımsız değişken yönetir. Bu nedenle errno ve strerror öznitelikleri başlatılamıyor. Hem neden olarak dizeleri geçirir:

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

ve diğer kaynaklardan gelen özel durumları sarar: her zamanki yerinde errno bulamazsınız nedeni budur

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 

Bu, bu durumda çalıştı, ancak neden özniteliği bir dize veya socket.error olabilir, has (had) its own problems with errno.

urllib2.py içinde URLError tanımı:

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 

Yani uzun lafın kısası, bu korkunç bir karmaşa.

  1. e.reason için e.reason numaralı telefonu kontrol etmelisiniz. Eğer öyleyse, hiçbir yerde errno olacaktır.
  2. socket.error mı? Bunun tuhaflıklarını hallet. Yine single string argument ile yükseltilebildiğinden errno özniteliği veya None özniteliği kaldırılabilir.
  3. IOError veya OSError'un bir alt sınıfı mıdır (EnvironmentError alt sınıfı)? Bunun errno özniteliğini okuyun ve en iyisi için umuyoruz.

Bu, muhtemelen sizin durumunuz için aşırı derecede ihtiyatlı olabilir, ancak kenarları anlamak güzeldir. Tornado had similar issues ve utility function to get errno from exception kullanıyor, ancak maalesef bu işlev URLErrors ile çalışmaz.

en azından bazı durumlarda ne kapsayabilecek:

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" kaynağına baktım ama bunun daha önce bu hatayı kontrol etmem gerektiğini bilmediğini fark ettim. Bunu deneyeceğim. Doğrulamak için biraz zaman alabilir, çünkü aslında hatanın atılmasına neden olan web sitesinin olup olmadığından emin değilim. –

+0

Kodunuz bizimkinden çok daha özlü, ama hemen hemen aynı. Sadece eklenmiş çok fazla kayıt var. Bu yaklaşım işe yararsa, biraz geri çekilmeye bakacağım, bu yüzden biraz daha net –

İlgili konular