Python3 如何正确处理超时并重试?

2017-02-24 02:07:16 +08:00
 HFX3389

一段为 POST 获取数据的代码,

#! /usr/local/python3
import urllib
import http
import time
import socket

timeout = 10
socket.setdefaulttimeout(timeout)


def up_post(username, password, page):
    data = {'username': username, 'password' : password}
    url = r"http://192.168.2.8/?page" + page
    postdata = bytes(urllib.parse.urlencode(data), encoding='gbk')
    response = urllib.request.urlopen(url, data=postdata)
    text = response.read().decode('gbk')
    print(text)
    if text.find("成功") != -1:
        return page + ":" + text
    else:
        return page + ":error"

username = "aaa"
password = "bbb"
page = 1
while page <= 99:
    try:
        static = up_post(username, password, page)
    except ( http.client.IncompleteRead, urllib.error.URLError, socket.timeout, ConnectionResetError) as e:
        time.sleep(5)
        static = up_post(username, password, page)
        while True:
            if static == page + ":" + static or static == page + ":error" or static == "":
                break

运行一段时间过后,会连续提示两个 timed out :

Traceback (most recent call last):
  File "mvc.py", line 103, in <module>
    static = up_post(username, password, page)
  File "mvc.py", line 27, in lan_up_post
    response = urllib.request.urlopen(url, data=postdata)
  File "/usr/local/lib/python3.6/urllib/request.py", line 223, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/local/lib/python3.6/urllib/request.py", line 526, in open
    response = self._open(req, data)
  File "/usr/local/lib/python3.6/urllib/request.py", line 544, in _open
    '_open', req)
  File "/usr/local/lib/python3.6/urllib/request.py", line 504, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python3.6/urllib/request.py", line 1346, in http_open
    return self.do_open( http.client.HTTPConnection, req)
  File "/usr/local/lib/python3.6/urllib/request.py", line 1321, in do_open
    r = h.getresponse()
  File "/usr/local/lib/python3.6/http/client.py", line 1331, in getresponse
    response.begin()
  File "/usr/local/lib/python3.6/http/client.py", line 297, in begin
    version, status, reason = self._read_status()
  File "/usr/local/lib/python3.6/http/client.py", line 258, in _read_status
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
  File "/usr/local/lib/python3.6/socket.py", line 586, in readinto
    return self._sock.recv_into(b)
socket.timeout: timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "mvc.py", line 106, in <module>
    static = up_post(username, password, page)
  File "mvc.py", line 27, in lan_up_post
    response = urllib.request.urlopen(url, data=postdata)
  File "/usr/local/lib/python3.6/urllib/request.py", line 223, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/local/lib/python3.6/urllib/request.py", line 526, in open
    response = self._open(req, data)
  File "/usr/local/lib/python3.6/urllib/request.py", line 544, in _open
    '_open', req)
  File "/usr/local/lib/python3.6/urllib/request.py", line 504, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python3.6/urllib/request.py", line 1346, in http_open
    return self.do_open( http.client.HTTPConnection, req)
  File "/usr/local/lib/python3.6/urllib/request.py", line 1321, in do_open
    r = h.getresponse()
  File "/usr/local/lib/python3.6/http/client.py", line 1331, in getresponse
    response.begin()
  File "/usr/local/lib/python3.6/http/client.py", line 297, in begin
    version, status, reason = self._read_status()
  File "/usr/local/lib/python3.6/http/client.py", line 258, in _read_status
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
  File "/usr/local/lib/python3.6/socket.py", line 586, in readinto
    return self._sock.recv_into(b)
socket.timeout: timed out

超时处理我只会 sleep 以后再重新运行一次获取代码,但是还是会出现两个 timed out 然后强行终止程序。

它提示 timed out 可以,但是我不想让它强行终止程序,我想让它不断重试!

咋搞啊?

11554 次点击
所在节点    Python
13 条回复
zeroten
2017-02-24 02:11:20 +08:00
把外部调用的函数加个装饰器,捕获异常并重试
HFX3389
2017-02-24 02:36:40 +08:00
这节点没有 APPEND 嘛?
我突然发现,似乎
if static == page + ":" + static or static == page + ":error" or static == "":
break
并没有用啊。
加不加都会 timed out
argsno
2017-02-24 06:20:55 +08:00
kindjeff
2017-02-24 07:08:13 +08:00
循环 try catch 呗
wannianma
2017-02-24 07:57:24 +08:00
最好设置个最高重试次数
cszeus
2017-02-24 08:04:59 +08:00
用 2 层循环?
while page <= 99:
gotData = False
reTry = 1
while reTry < 5 and not gotData:
try:
reTry += 1
static = up_post()
gotData = True
except:
pass
rogerchen
2017-02-24 08:10:43 +08:00
while try catch timeout break
herozhang
2017-02-24 08:11:56 +08:00
有个包叫做 retry ,可以试一下
zh5e
2017-02-24 09:05:03 +08:00
@argsno 这个方法好
lerry
2017-02-24 09:29:30 +08:00
web 请求函数单独摘出来,手动捕获超时,超时就递归请求,正常就返回,还可以传一个最大尝试次数的参数
awanabe
2017-02-24 10:32:17 +08:00
requests 库有 timeout 选项的
Ge4Los
2017-02-24 10:49:16 +08:00
requests 有 timeout 和 retry 的配置。可以分别设置连接超时和读取超时。
phithon
2017-02-24 18:31:37 +08:00
@argsno 对,我一直用这个库

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/342795

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX