2013-12-13 23 views
47

Wenn Python 2.7 mit urllib2 Daten von einer API abrufen, erhalte ich den Fehler [Errno 104] Connection reset by peer. Was verursacht den Fehler und wie sollte der Fehler behandelt werden, damit das Skript nicht abstürzt?Python-Behandlung socket.error: [Errno 104] Verbindung durch Peer zurückgesetzt

ticker.py

def urlopen(url): 
    response = None 
    request = urllib2.Request(url=url) 
    try: 
     response = urllib2.urlopen(request).read() 
    except urllib2.HTTPError as err: 
     print "HTTPError: {} ({})".format(url, err.code) 
    except urllib2.URLError as err: 
     print "URLError: {} ({})".format(url, err.reason) 
    except httplib.BadStatusLine as err: 
     print "BadStatusLine: {}".format(url) 
    return response 

def get_rate(from_currency="EUR", to_currency="USD"): 
    url = "https://finance.yahoo.com/d/quotes.csv?f=sl1&s=%s%s=X" % (
     from_currency, to_currency) 
    data = urlopen(url) 
    if "%s%s" % (from_currency, to_currency) in data: 
     return float(data.strip().split(",")[1]) 
    return None 


counter = 0 
while True: 

    counter = counter + 1 
    if counter==0 or counter%10: 
     rateEurUsd = float(get_rate('EUR', 'USD')) 

    # does more stuff here 

Traceback

Traceback (most recent call last): 
    File "/var/www/testApp/python/ticker.py", line 71, in <module> 
    rateEurUsd = float(get_rate('EUR', 'USD')) 
    File "/var/www/testApp/python/ticker.py", line 29, in get_exchange_rate 
    data = urlopen(url) 
    File "/var/www/testApp/python/ticker.py", line 16, in urlopen 
    response = urllib2.urlopen(request).read() 
    File "/usr/lib/python2.7/urllib2.py", line 126, in urlopen 
    return _opener.open(url, data, timeout) 
    File "/usr/lib/python2.7/urllib2.py", line 406, in open 
    response = meth(req, response) 
    File "/usr/lib/python2.7/urllib2.py", line 519, in http_response 
    'http', request, response, code, msg, hdrs) 
    File "/usr/lib/python2.7/urllib2.py", line 438, in error 
    result = self._call_chain(*args) 
    File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain 
    result = func(*args) 
    File "/usr/lib/python2.7/urllib2.py", line 625, in http_error_302 
    return self.parent.open(new, timeout=req.timeout) 
    File "/usr/lib/python2.7/urllib2.py", line 406, in open 
    response = meth(req, response) 
    File "/usr/lib/python2.7/urllib2.py", line 519, in http_response 
    'http', request, response, code, msg, hdrs) 
    File "/usr/lib/python2.7/urllib2.py", line 438, in error 
    result = self._call_chain(*args) 
    File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain 
    result = func(*args) 
    File "/usr/lib/python2.7/urllib2.py", line 625, in http_error_302 
    return self.parent.open(new, timeout=req.timeout) 
    File "/usr/lib/python2.7/urllib2.py", line 400, in open 
    response = self._open(req, data) 
    File "/usr/lib/python2.7/urllib2.py", line 418, in _open 
    '_open', req) 
    File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain 
    result = func(*args) 
    File "/usr/lib/python2.7/urllib2.py", line 1207, in http_open 
    return self.do_open(httplib.HTTPConnection, req) 
    File "/usr/lib/python2.7/urllib2.py", line 1180, in do_open 
    r = h.getresponse(buffering=True) 
    File "/usr/lib/python2.7/httplib.py", line 1030, in getresponse 
    response.begin() 
    File "/usr/lib/python2.7/httplib.py", line 407, in begin 
    version, status, reason = self._read_status() 
    File "/usr/lib/python2.7/httplib.py", line 365, in _read_status 
    line = self.fp.readline() 
    File "/usr/lib/python2.7/socket.py", line 447, in readline 
    data = self._sock.recv(self._rbufsize) 
socket.error: [Errno 104] Connection reset by peer 
error: Forever detected script exited with code: 1 
+0

Auf Arch Linux funktioniert Get_rate gut für mich. Sind Sie sicher, dass Sie nicht gefiltert werden? Können Sie diese URL in einem Browser laden? – korylprince

+0

@korylprince Es funktioniert gut in einem Browser, und das Skript läuft eine Weile gut, bevor der Fehler auftritt. Wenn ich den Fehler nicht vermeiden kann, wie sollte der Fehler behandelt werden, damit er nicht abstürzt, und wahrscheinlich den zuletzt abgerufenen Wert verwendet? –

Antwort

87

"Connection reset by peer" is the TCP/IP equivalent of slamming the phone back on the hook. It's more polite than merely not replying, leaving one hanging. But it's not the FIN-ACK expected of the truly polite TCP/IP converseur. (From other SO answer)

So können Sie nicht etwas dagegen tun, ist es das Problem des Servers.

Aber Sie könnten try .. except Block verwenden, um diese Ausnahme zu behandeln:

from socket import error as SocketError 
import errno 

try: 
    response = urllib2.urlopen(request).read() 
except SocketError as e: 
    if e.errno != errno.ECONNRESET: 
     raise # Not error we are looking for 
    pass # Handle error here. 
+0

Stimmt es, dass der Administrator des Servers normalerweise diese Methode verwendet, um die potenziellen Scrapping-Anforderungen eines Clients zu blockieren, oder handelt es sich eher um einen unbeabsichtigten Fehler? Jetzt frage ich mich ob ich absichtlich blockiert bin oder nicht ... – Blaszard

0

Sie können versuchen, einige time.sleep Anrufe zu Ihrem Code hinzuzufügen.

Es scheint, als würde die Serverseite die Anzahl der Anfragen pro Zeiteinheit (Stunde, Tag, Sekunde) als Sicherheitsproblem begrenzen. Sie müssen raten, wie viele (möglicherweise mit einem anderen Skript mit einem Zähler?) Und passen Sie Ihr Skript, um dieses Limit nicht zu überschreiten.

Um zu vermeiden, dass Ihr Code abstürzt, versuchen Sie, diesen Fehler mit try .. except um die Urllib2-Aufrufe zu fangen.

Verwandte Themen