简体   繁体   English

Python 处理 socket.error: [Errno 104] Connection reset by peer

[英]Python handling socket.error: [Errno 104] Connection reset by peer

When using Python 2.7 with urllib2 to retrieve data from an API, I get the error [Errno 104] Connection reset by peer .当使用带有urllib2的 Python 2.7 从 API 检索数据时,我收到错误[Errno 104] Connection reset by peer Whats causing the error, and how should the error be handled so that the script does not crash?是什么导致了错误,应该如何处理错误以使脚本不会崩溃?

ticker.py股票代码.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

"Connection reset by peer" is the TCP/IP equivalent of slamming the phone back on the hook. “由对等方重置连接”是 TCP/IP 等价物,相当于将电话重新挂断。 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.但这不是真正礼貌的 TCP/IP 对话者所期望的 FIN-ACK。 ( From other SO answer ) 来自其他SO答案

So you can't do anything about it, it is the issue of the server.所以你无能为力,这是服务器的问题。

But you could use try .. except block to handle that exception:但是您可以使用try .. except块来处理该异常:

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.

You can try to add some time.sleep calls to your code.您可以尝试在代码中添加一些time.sleep调用。

It seems like the server side limits the amount of requests per timeunit (hour, day, second) as a security issue.服务器端似乎将每个时间单位(小时、天、秒)的请求数量限制为安全问题。 You need to guess how many (maybe using another script with a counter?) and adjust your script to not surpass this limit.您需要猜测有多少(也许使用带有计数器的另一个脚本?)并调整您的脚本以不超过此限制。

In order to avoid your code from crashing, try to catch this error with try .. except around the urllib2 calls.为了避免您的代码崩溃,请尝试使用try .. except urllib2 调用捕获此错误。

There is a way to catch the error directly in the except clause with ConnectionResetError, better to isolate the right error.有一种方法可以使用ConnectionResetError 直接在except 子句中捕获错误,更好地隔离正确的错误。 This example also catches the timeout.此示例还捕获超时。

from urllib.request import urlopen 
from socket import timeout

url = "http://......"
try: 
    string = urlopen(url, timeout=5).read()
except ConnectionResetError:
    print("==> ConnectionResetError")
    pass
except timeout: 
    print("==> Timeout")
    pass

there are 2 solution you can try.您可以尝试两种解决方案。

  1. request too frequently.要求太频繁。 try sleep after per request每个请求后尝试sleep
time.sleep(1)
  1. the server detect the request client is python, so reject.服务器检测到请求客户端是python,所以拒绝。 add User-Agent in header to handle this.在 header 中添加User-Agent来处理这个问题。
    headers = {
        "Content-Type": "application/json;charset=UTF-8",
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)"
    }
    try:
        res = requests.post("url", json=req, headers=headers)
    except Exception as e:
        print(e)
        pass

the second solution save me第二种解决方案救了我

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Python socket.error:[Errno 104]由peer重置连接 - Python socket.error: [Errno 104] Connection reset by peer MRJob:socket.error:[Errno 104]通过对等方重置连接 - MRJob: socket.error: [Errno 104] Connection reset by peer Python套接字ConnectionResetError:[Errno 54]对等方与socket.error的连接重置:[Errno 104]对等方重置连接 - Python socket ConnectionResetError: [Errno 54] Connection reset by peer vs socket.error: [Errno 104] Connection reset by peer Python请求/ urllib2 socket.error:[Errno 104]对等重置连接 - Python requests / urllib2 socket.error: [Errno 104] Connection reset by peer 使用try处理套接字错误,但[Errno 104]会被对等方重置 - Handling socket error with try, except [Errno 104] Connection reset by peer 高负载下的Rabbitmq:Socket.error [Errno 104]对等重置连接 - Rabbitmq on high load: Socket.error [Errno 104] Connection reset by peer socket.error:[Errno 54]由对等Selenium-python重置连接 - socket.error: [Errno 54] Connection reset by peer Selenium-python Python:socket.error:[Error55]对等重置连接 - Python: socket.error: [Error55] Connection reset by peer ConnectionResetError:[Errno 104]由对等Python 3重置连接 - ConnectionResetError: [Errno 104] Connection reset by peer python 3 在Python 2.7中由peer [errno 104]重置连接 - Connection reset by peer [errno 104] in Python 2.7
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM